Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <linux/kernel.h>
  3#include <linux/module.h>
  4#include <linux/slab.h>
  5#include <linux/delay.h>
  6#include <linux/ioport.h>
  7#include <linux/mtd/mtd.h>
  8#include <linux/platform_device.h>
  9#include <linux/bcma/bcma.h>
 10
 11#include "bcm47xxsflash.h"
 12
 13MODULE_LICENSE("GPL");
 14MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
 15
 16static const char * const probes[] = { "bcm47xxpart", NULL };
 17
 18/**************************************************
 19 * Various helpers
 20 **************************************************/
 21
 22static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
 23{
 24	int i;
 25
 26	b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
 27	for (i = 0; i < 1000; i++) {
 28		if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
 29		      BCMA_CC_FLASHCTL_BUSY))
 30			return;
 31		cpu_relax();
 32	}
 33	pr_err("Control command failed (timeout)!\n");
 34}
 35
 36static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
 37{
 38	unsigned long deadline = jiffies + timeout;
 39
 40	do {
 41		switch (b47s->type) {
 42		case BCM47XXSFLASH_TYPE_ST:
 43			bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
 44			if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 45			      SR_ST_WIP))
 46				return 0;
 47			break;
 48		case BCM47XXSFLASH_TYPE_ATMEL:
 49			bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
 50			if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 51			    SR_AT_READY)
 52				return 0;
 53			break;
 54		}
 55
 56		cpu_relax();
 57		udelay(1);
 58	} while (!time_after_eq(jiffies, deadline));
 59
 60	pr_err("Timeout waiting for flash to be ready!\n");
 61
 62	return -EBUSY;
 63}
 64
 65/**************************************************
 66 * MTD ops
 67 **************************************************/
 68
 69static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
 70{
 71	struct bcm47xxsflash *b47s = mtd->priv;
 72
 73	switch (b47s->type) {
 74	case BCM47XXSFLASH_TYPE_ST:
 75		bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
 76		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr);
 77		/* Newer flashes have "sub-sectors" which can be erased
 78		 * independently with a new command: ST_SSE. The ST_SE command
 79		 * erases 64KB just as before.
 80		 */
 81		if (b47s->blocksize < (64 * 1024))
 82			bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE);
 83		else
 84			bcm47xxsflash_cmd(b47s, OPCODE_ST_SE);
 85		break;
 86	case BCM47XXSFLASH_TYPE_ATMEL:
 87		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1);
 88		bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE);
 89		break;
 90	}
 91
 92	return bcm47xxsflash_poll(b47s, HZ);
 93}
 94
 95static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 96			      size_t *retlen, u_char *buf)
 97{
 98	struct bcm47xxsflash *b47s = mtd->priv;
 99	size_t orig_len = len;
100
101	/* Check address range */
102	if ((from + len) > mtd->size)
103		return -EINVAL;
104
105	/* Read as much as possible using fast MMIO window */
106	if (from < BCM47XXSFLASH_WINDOW_SZ) {
107		size_t memcpy_len;
108
109		memcpy_len = min(len, (size_t)(BCM47XXSFLASH_WINDOW_SZ - from));
110		memcpy_fromio(buf, b47s->window + from, memcpy_len);
111		from += memcpy_len;
112		len -= memcpy_len;
113		buf += memcpy_len;
114	}
115
116	/* Use indirect access for content out of the window */
117	for (; len; len--) {
118		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, from++);
119		bcm47xxsflash_cmd(b47s, OPCODE_ST_READ4B);
120		*buf++ = b47s->cc_read(b47s, BCMA_CC_FLASHDATA);
121	}
122
123	*retlen = orig_len;
124
125	return orig_len;
126}
127
128static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
129				  const u_char *buf)
130{
131	struct bcm47xxsflash *b47s = mtd->priv;
132	int written = 0;
133
134	/* Enable writes */
135	bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
136
137	/* Write first byte */
138	b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset);
139	b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
140
141	/* Program page */
142	if (b47s->bcma_cc->core->id.rev < 20) {
143		bcm47xxsflash_cmd(b47s, OPCODE_ST_PP);
144		return 1; /* 1B written */
145	}
146
147	/* Program page and set CSA (on newer chips we can continue writing) */
148	bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP);
149	offset++;
150	len--;
151	written++;
152
153	while (len > 0) {
154		/* Page boundary, another function call is needed */
155		if ((offset & 0xFF) == 0)
156			break;
157
158		bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++);
159		offset++;
160		len--;
161		written++;
162	}
163
164	/* All done, drop CSA & poll */
165	b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0);
166	udelay(1);
167	if (bcm47xxsflash_poll(b47s, HZ / 10))
168		pr_err("Flash rejected dropping CSA\n");
169
170	return written;
171}
172
173static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len,
174				  const u_char *buf)
175{
176	struct bcm47xxsflash *b47s = mtd->priv;
177	u32 mask = b47s->blocksize - 1;
178	u32 page = (offset & ~mask) << 1;
179	u32 byte = offset & mask;
180	int written = 0;
181
182	/* If we don't overwrite whole page, read it to the buffer first */
183	if (byte || (len < b47s->blocksize)) {
184		int err;
185
186		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
187		bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD);
188		/* 250 us for AT45DB321B */
189		err = bcm47xxsflash_poll(b47s, HZ / 1000);
190		if (err) {
191			pr_err("Timeout reading page 0x%X info buffer\n", page);
192			return err;
193		}
194	}
195
196	/* Change buffer content with our data */
197	while (len > 0) {
198		/* Page boundary, another function call is needed */
199		if (byte == b47s->blocksize)
200			break;
201
202		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++);
203		b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
204		bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE);
205		len--;
206		written++;
207	}
208
209	/* Program page with the buffer content */
210	b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
211	bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM);
212
213	return written;
214}
215
216static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
217			       size_t *retlen, const u_char *buf)
218{
219	struct bcm47xxsflash *b47s = mtd->priv;
220	int written;
221
222	/* Writing functions can return without writing all passed data, for
223	 * example when the hardware is too old or when we git page boundary.
224	 */
225	while (len > 0) {
226		switch (b47s->type) {
227		case BCM47XXSFLASH_TYPE_ST:
228			written = bcm47xxsflash_write_st(mtd, to, len, buf);
229			break;
230		case BCM47XXSFLASH_TYPE_ATMEL:
231			written = bcm47xxsflash_write_at(mtd, to, len, buf);
232			break;
233		default:
234			BUG_ON(1);
235		}
236		if (written < 0) {
237			pr_err("Error writing at offset 0x%llX\n", to);
238			return written;
239		}
240		to += (loff_t)written;
241		len -= written;
242		*retlen += written;
243		buf += written;
244	}
245
246	return 0;
247}
248
249static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
250				   struct device *dev)
251{
252	struct mtd_info *mtd = &b47s->mtd;
253
254	mtd->priv = b47s;
255	mtd->dev.parent = dev;
256	mtd->name = "bcm47xxsflash";
257
258	mtd->type = MTD_NORFLASH;
259	mtd->flags = MTD_CAP_NORFLASH;
260	mtd->size = b47s->size;
261	mtd->erasesize = b47s->blocksize;
262	mtd->writesize = 1;
263	mtd->writebufsize = 1;
264
265	mtd->_erase = bcm47xxsflash_erase;
266	mtd->_read = bcm47xxsflash_read;
267	mtd->_write = bcm47xxsflash_write;
268}
269
270/**************************************************
271 * BCMA
272 **************************************************/
273
274static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
275{
276	return bcma_cc_read32(b47s->bcma_cc, offset);
277}
278
279static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
280					u32 value)
281{
282	bcma_cc_write32(b47s->bcma_cc, offset, value);
283}
284
285static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
286{
287	struct device *dev = &pdev->dev;
288	struct bcma_sflash *sflash = dev_get_platdata(dev);
289	struct bcm47xxsflash *b47s;
290	struct resource *res;
291	int err;
292
293	b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
294	if (!b47s)
295		return -ENOMEM;
296
297	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
298	if (!res) {
299		dev_err(dev, "invalid resource\n");
300		return -EINVAL;
301	}
302	if (!devm_request_mem_region(dev, res->start, resource_size(res),
303				     res->name)) {
304		dev_err(dev, "can't request region for resource %pR\n", res);
305		return -EBUSY;
306	}
307
308	b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
309	b47s->cc_read = bcm47xxsflash_bcma_cc_read;
310	b47s->cc_write = bcm47xxsflash_bcma_cc_write;
311
312	/*
313	 * On old MIPS devices cache was magically invalidated when needed,
314	 * allowing us to use cached access and gain some performance. Trying
315	 * the same on ARM based BCM53573 results in flash corruptions, we need
316	 * to use uncached access for it.
317	 *
318	 * It may be arch specific, but right now there is only 1 ARM SoC using
319	 * this driver, so let's follow Broadcom's reference code and check
320	 * ChipCommon revision.
321	 */
322	if (b47s->bcma_cc->core->id.rev == 54)
323		b47s->window = ioremap(res->start, resource_size(res));
324	else
325		b47s->window = ioremap_cache(res->start, resource_size(res));
326	if (!b47s->window) {
327		dev_err(dev, "ioremap failed for resource %pR\n", res);
328		return -ENOMEM;
329	}
330
331	switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
332	case BCMA_CC_FLASHT_STSER:
333		b47s->type = BCM47XXSFLASH_TYPE_ST;
334		break;
335	case BCMA_CC_FLASHT_ATSER:
336		b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
337		break;
338	}
339
340	b47s->blocksize = sflash->blocksize;
341	b47s->numblocks = sflash->numblocks;
342	b47s->size = sflash->size;
343	bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
344
345	platform_set_drvdata(pdev, b47s);
346
347	err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
348	if (err) {
349		pr_err("Failed to register MTD device: %d\n", err);
350		iounmap(b47s->window);
351		return err;
352	}
353
354	if (bcm47xxsflash_poll(b47s, HZ / 10))
355		pr_warn("Serial flash busy\n");
356
357	return 0;
358}
359
360static void bcm47xxsflash_bcma_remove(struct platform_device *pdev)
361{
362	struct bcm47xxsflash *b47s = platform_get_drvdata(pdev);
363
364	mtd_device_unregister(&b47s->mtd);
365	iounmap(b47s->window);
 
 
366}
367
368static struct platform_driver bcma_sflash_driver = {
369	.probe	= bcm47xxsflash_bcma_probe,
370	.remove_new = bcm47xxsflash_bcma_remove,
371	.driver = {
372		.name = "bcma_sflash",
373	},
374};
375
376/**************************************************
377 * Init
378 **************************************************/
379
380module_platform_driver(bcma_sflash_driver);
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <linux/kernel.h>
  3#include <linux/module.h>
  4#include <linux/slab.h>
  5#include <linux/delay.h>
  6#include <linux/ioport.h>
  7#include <linux/mtd/mtd.h>
  8#include <linux/platform_device.h>
  9#include <linux/bcma/bcma.h>
 10
 11#include "bcm47xxsflash.h"
 12
 13MODULE_LICENSE("GPL");
 14MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
 15
 16static const char * const probes[] = { "bcm47xxpart", NULL };
 17
 18/**************************************************
 19 * Various helpers
 20 **************************************************/
 21
 22static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
 23{
 24	int i;
 25
 26	b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
 27	for (i = 0; i < 1000; i++) {
 28		if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
 29		      BCMA_CC_FLASHCTL_BUSY))
 30			return;
 31		cpu_relax();
 32	}
 33	pr_err("Control command failed (timeout)!\n");
 34}
 35
 36static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
 37{
 38	unsigned long deadline = jiffies + timeout;
 39
 40	do {
 41		switch (b47s->type) {
 42		case BCM47XXSFLASH_TYPE_ST:
 43			bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
 44			if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 45			      SR_ST_WIP))
 46				return 0;
 47			break;
 48		case BCM47XXSFLASH_TYPE_ATMEL:
 49			bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
 50			if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 51			    SR_AT_READY)
 52				return 0;
 53			break;
 54		}
 55
 56		cpu_relax();
 57		udelay(1);
 58	} while (!time_after_eq(jiffies, deadline));
 59
 60	pr_err("Timeout waiting for flash to be ready!\n");
 61
 62	return -EBUSY;
 63}
 64
 65/**************************************************
 66 * MTD ops
 67 **************************************************/
 68
 69static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
 70{
 71	struct bcm47xxsflash *b47s = mtd->priv;
 72
 73	switch (b47s->type) {
 74	case BCM47XXSFLASH_TYPE_ST:
 75		bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
 76		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr);
 77		/* Newer flashes have "sub-sectors" which can be erased
 78		 * independently with a new command: ST_SSE. The ST_SE command
 79		 * erases 64KB just as before.
 80		 */
 81		if (b47s->blocksize < (64 * 1024))
 82			bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE);
 83		else
 84			bcm47xxsflash_cmd(b47s, OPCODE_ST_SE);
 85		break;
 86	case BCM47XXSFLASH_TYPE_ATMEL:
 87		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1);
 88		bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE);
 89		break;
 90	}
 91
 92	return bcm47xxsflash_poll(b47s, HZ);
 93}
 94
 95static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 96			      size_t *retlen, u_char *buf)
 97{
 98	struct bcm47xxsflash *b47s = mtd->priv;
 99	size_t orig_len = len;
100
101	/* Check address range */
102	if ((from + len) > mtd->size)
103		return -EINVAL;
104
105	/* Read as much as possible using fast MMIO window */
106	if (from < BCM47XXSFLASH_WINDOW_SZ) {
107		size_t memcpy_len;
108
109		memcpy_len = min(len, (size_t)(BCM47XXSFLASH_WINDOW_SZ - from));
110		memcpy_fromio(buf, b47s->window + from, memcpy_len);
111		from += memcpy_len;
112		len -= memcpy_len;
113		buf += memcpy_len;
114	}
115
116	/* Use indirect access for content out of the window */
117	for (; len; len--) {
118		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, from++);
119		bcm47xxsflash_cmd(b47s, OPCODE_ST_READ4B);
120		*buf++ = b47s->cc_read(b47s, BCMA_CC_FLASHDATA);
121	}
122
123	*retlen = orig_len;
124
125	return orig_len;
126}
127
128static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
129				  const u_char *buf)
130{
131	struct bcm47xxsflash *b47s = mtd->priv;
132	int written = 0;
133
134	/* Enable writes */
135	bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
136
137	/* Write first byte */
138	b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset);
139	b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
140
141	/* Program page */
142	if (b47s->bcma_cc->core->id.rev < 20) {
143		bcm47xxsflash_cmd(b47s, OPCODE_ST_PP);
144		return 1; /* 1B written */
145	}
146
147	/* Program page and set CSA (on newer chips we can continue writing) */
148	bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP);
149	offset++;
150	len--;
151	written++;
152
153	while (len > 0) {
154		/* Page boundary, another function call is needed */
155		if ((offset & 0xFF) == 0)
156			break;
157
158		bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++);
159		offset++;
160		len--;
161		written++;
162	}
163
164	/* All done, drop CSA & poll */
165	b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0);
166	udelay(1);
167	if (bcm47xxsflash_poll(b47s, HZ / 10))
168		pr_err("Flash rejected dropping CSA\n");
169
170	return written;
171}
172
173static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len,
174				  const u_char *buf)
175{
176	struct bcm47xxsflash *b47s = mtd->priv;
177	u32 mask = b47s->blocksize - 1;
178	u32 page = (offset & ~mask) << 1;
179	u32 byte = offset & mask;
180	int written = 0;
181
182	/* If we don't overwrite whole page, read it to the buffer first */
183	if (byte || (len < b47s->blocksize)) {
184		int err;
185
186		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
187		bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD);
188		/* 250 us for AT45DB321B */
189		err = bcm47xxsflash_poll(b47s, HZ / 1000);
190		if (err) {
191			pr_err("Timeout reading page 0x%X info buffer\n", page);
192			return err;
193		}
194	}
195
196	/* Change buffer content with our data */
197	while (len > 0) {
198		/* Page boundary, another function call is needed */
199		if (byte == b47s->blocksize)
200			break;
201
202		b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++);
203		b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
204		bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE);
205		len--;
206		written++;
207	}
208
209	/* Program page with the buffer content */
210	b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
211	bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM);
212
213	return written;
214}
215
216static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
217			       size_t *retlen, const u_char *buf)
218{
219	struct bcm47xxsflash *b47s = mtd->priv;
220	int written;
221
222	/* Writing functions can return without writing all passed data, for
223	 * example when the hardware is too old or when we git page boundary.
224	 */
225	while (len > 0) {
226		switch (b47s->type) {
227		case BCM47XXSFLASH_TYPE_ST:
228			written = bcm47xxsflash_write_st(mtd, to, len, buf);
229			break;
230		case BCM47XXSFLASH_TYPE_ATMEL:
231			written = bcm47xxsflash_write_at(mtd, to, len, buf);
232			break;
233		default:
234			BUG_ON(1);
235		}
236		if (written < 0) {
237			pr_err("Error writing at offset 0x%llX\n", to);
238			return written;
239		}
240		to += (loff_t)written;
241		len -= written;
242		*retlen += written;
243		buf += written;
244	}
245
246	return 0;
247}
248
249static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
250				   struct device *dev)
251{
252	struct mtd_info *mtd = &b47s->mtd;
253
254	mtd->priv = b47s;
255	mtd->dev.parent = dev;
256	mtd->name = "bcm47xxsflash";
257
258	mtd->type = MTD_NORFLASH;
259	mtd->flags = MTD_CAP_NORFLASH;
260	mtd->size = b47s->size;
261	mtd->erasesize = b47s->blocksize;
262	mtd->writesize = 1;
263	mtd->writebufsize = 1;
264
265	mtd->_erase = bcm47xxsflash_erase;
266	mtd->_read = bcm47xxsflash_read;
267	mtd->_write = bcm47xxsflash_write;
268}
269
270/**************************************************
271 * BCMA
272 **************************************************/
273
274static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
275{
276	return bcma_cc_read32(b47s->bcma_cc, offset);
277}
278
279static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
280					u32 value)
281{
282	bcma_cc_write32(b47s->bcma_cc, offset, value);
283}
284
285static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
286{
287	struct device *dev = &pdev->dev;
288	struct bcma_sflash *sflash = dev_get_platdata(dev);
289	struct bcm47xxsflash *b47s;
290	struct resource *res;
291	int err;
292
293	b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
294	if (!b47s)
295		return -ENOMEM;
296
297	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
298	if (!res) {
299		dev_err(dev, "invalid resource\n");
300		return -EINVAL;
301	}
302	if (!devm_request_mem_region(dev, res->start, resource_size(res),
303				     res->name)) {
304		dev_err(dev, "can't request region for resource %pR\n", res);
305		return -EBUSY;
306	}
307
308	b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
309	b47s->cc_read = bcm47xxsflash_bcma_cc_read;
310	b47s->cc_write = bcm47xxsflash_bcma_cc_write;
311
312	/*
313	 * On old MIPS devices cache was magically invalidated when needed,
314	 * allowing us to use cached access and gain some performance. Trying
315	 * the same on ARM based BCM53573 results in flash corruptions, we need
316	 * to use uncached access for it.
317	 *
318	 * It may be arch specific, but right now there is only 1 ARM SoC using
319	 * this driver, so let's follow Broadcom's reference code and check
320	 * ChipCommon revision.
321	 */
322	if (b47s->bcma_cc->core->id.rev == 54)
323		b47s->window = ioremap(res->start, resource_size(res));
324	else
325		b47s->window = ioremap_cache(res->start, resource_size(res));
326	if (!b47s->window) {
327		dev_err(dev, "ioremap failed for resource %pR\n", res);
328		return -ENOMEM;
329	}
330
331	switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
332	case BCMA_CC_FLASHT_STSER:
333		b47s->type = BCM47XXSFLASH_TYPE_ST;
334		break;
335	case BCMA_CC_FLASHT_ATSER:
336		b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
337		break;
338	}
339
340	b47s->blocksize = sflash->blocksize;
341	b47s->numblocks = sflash->numblocks;
342	b47s->size = sflash->size;
343	bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
344
345	platform_set_drvdata(pdev, b47s);
346
347	err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
348	if (err) {
349		pr_err("Failed to register MTD device: %d\n", err);
350		iounmap(b47s->window);
351		return err;
352	}
353
354	if (bcm47xxsflash_poll(b47s, HZ / 10))
355		pr_warn("Serial flash busy\n");
356
357	return 0;
358}
359
360static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
361{
362	struct bcm47xxsflash *b47s = platform_get_drvdata(pdev);
363
364	mtd_device_unregister(&b47s->mtd);
365	iounmap(b47s->window);
366
367	return 0;
368}
369
370static struct platform_driver bcma_sflash_driver = {
371	.probe	= bcm47xxsflash_bcma_probe,
372	.remove = bcm47xxsflash_bcma_remove,
373	.driver = {
374		.name = "bcma_sflash",
375	},
376};
377
378/**************************************************
379 * Init
380 **************************************************/
381
382module_platform_driver(bcma_sflash_driver);