Re: RFC: use datacs is smc91x driver

From: Nicolas Pitre
Date: Tue Jan 25 2005 - 11:52:55 EST


On Tue, 25 Jan 2005, Ian Campbell wrote:

> Sounds good. Are you happy for me to send the version below to Andrew
> and Jeff for inclusion? compiled on lubbock and neponset, compiled and
> tested on my platform.
>
> Cheers,
> Ian.
>
> Signed-off-by: Ian Campbell <icampbell@xxxxxxxxx>

Signed-off-by: Nicolas Pitre <nico@xxxxxxx>


>
> Index: 2.6/drivers/net/smc91x.c
> ===================================================================
> --- 2.6.orig/drivers/net/smc91x.c 2005-01-25 08:48:28.000000000 +0000
> +++ 2.6/drivers/net/smc91x.c 2005-01-25 15:56:00.405373349 +0000
> @@ -210,6 +210,10 @@
>
> spinlock_t lock;
>
> +#ifdef SMC_CAN_USE_DATACS
> + u32 *datacs;
> +#endif
> +
> #ifdef SMC_USE_PXA_DMA
> /* DMA needs the physical address of the chip */
> u_long physaddr;
> @@ -1998,16 +2002,21 @@
> return retval;
> }
>
> -static int smc_enable_device(unsigned long attrib_phys)
> +static int smc_enable_device(struct platform_device *pdev)
> {
> unsigned long flags;
> unsigned char ecor, ecsr;
> void *addr;
> + struct resource * res;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> + if (!res)
> + return 0;
>
> /*
> * Map the attribute space. This is overkill, but clean.
> */
> - addr = ioremap(attrib_phys, ATTRIB_SIZE);
> + addr = ioremap(res->start, ATTRIB_SIZE);
> if (!addr)
> return -ENOMEM;
>
> @@ -2055,6 +2064,62 @@
> return 0;
> }
>
> +static int smc_request_attrib(struct platform_device *pdev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> +
> + if (!res)
> + return 0;
> +
> + if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
> + return -EBUSY;
> +
> + return 0;
> +}
> +
> +static void smc_release_attrib(struct platform_device *pdev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> +
> + if (res)
> + release_mem_region(res->start, ATTRIB_SIZE);
> +}
> +
> +#ifdef SMC_CAN_USE_DATACS
> +static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
> + struct smc_local *lp = netdev_priv(ndev);
> +
> + if (!res)
> + return;
> +
> + if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
> + printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
> + return;
> + }
> +
> + lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
> +}
> +
> +static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
> +{
> + struct smc_local *lp = netdev_priv(ndev);
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
> +
> + if (lp->datacs)
> + iounmap(lp->datacs);
> +
> + lp->datacs = NULL;
> +
> + if (res)
> + release_mem_region(res->start, SMC_DATA_EXTENT);
> +}
> +#else
> +static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
> +static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
> +#endif
> +
> /*
> * smc_init(void)
> * Input parameters:
> @@ -2070,20 +2135,20 @@
> {
> struct platform_device *pdev = to_platform_device(dev);
> struct net_device *ndev;
> - struct resource *res, *ext = NULL;
> + struct resource *res;
> unsigned int *addr;
> int ret;
>
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
> + if (!res)
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> if (!res) {
> ret = -ENODEV;
> goto out;
> }
>
> - /*
> - * Request the regions.
> - */
> - if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
> +
> + if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
> ret = -EBUSY;
> goto out;
> }
> @@ -2092,7 +2157,7 @@
> if (!ndev) {
> printk("%s: could not allocate device.\n", CARDNAME);
> ret = -ENOMEM;
> - goto release_1;
> + goto out_release_io;
> }
> SET_MODULE_OWNER(ndev);
> SET_NETDEV_DEV(ndev, dev);
> @@ -2100,42 +2165,26 @@
> ndev->dma = (unsigned char)-1;
> ndev->irq = platform_get_irq(pdev, 0);
>
> - ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> - if (ext) {
> - if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
> - ret = -EBUSY;
> - goto release_1;
> - }
> -
> + ret = smc_request_attrib(pdev);
> + if (ret)
> + goto out_free_netdev;
> #if defined(CONFIG_SA1100_ASSABET)
> - NCR_0 |= NCR_ENET_OSC_EN;
> + NCR_0 |= NCR_ENET_OSC_EN;
> #endif
> -
> - ret = smc_enable_device(ext->start);
> - if (ret)
> - goto release_both;
> - }
> + ret = smc_enable_device(pdev);
> + if (ret)
> + goto out_release_attrib;
>
> addr = ioremap(res->start, SMC_IO_EXTENT);
> if (!addr) {
> ret = -ENOMEM;
> - goto release_both;
> + goto out_release_attrib;
> }
>
> dev_set_drvdata(dev, ndev);
> ret = smc_probe(ndev, (unsigned long)addr);
> - if (ret != 0) {
> - dev_set_drvdata(dev, NULL);
> - iounmap(addr);
> - release_both:
> - if (ext)
> - release_mem_region(ext->start, ATTRIB_SIZE);
> - free_netdev(ndev);
> - release_1:
> - release_mem_region(res->start, SMC_IO_EXTENT);
> - out:
> - printk("%s: not found (%d).\n", CARDNAME, ret);
> - }
> + if (ret != 0)
> + goto out_iounmap;
> #ifdef SMC_USE_PXA_DMA
> else {
> struct smc_local *lp = netdev_priv(ndev);
> @@ -2143,6 +2192,22 @@
> }
> #endif
>
> + smc_request_datacs(pdev, ndev);
> +
> + return 0;
> +
> + out_iounmap:
> + dev_set_drvdata(dev, NULL);
> + iounmap(addr);
> + out_release_attrib:
> + smc_release_attrib(pdev);
> + out_free_netdev:
> + free_netdev(ndev);
> + out_release_io:
> + release_mem_region(res->start, SMC_IO_EXTENT);
> + out:
> + printk("%s: not found (%d).\n", CARDNAME, ret);
> +
> return ret;
> }
>
> @@ -2163,10 +2228,13 @@
> pxa_free_dma(ndev->dma);
> #endif
> iounmap((void *)ndev->base_addr);
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> - if (res)
> - release_mem_region(res->start, ATTRIB_SIZE);
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> + smc_release_datacs(pdev,ndev);
> + smc_release_attrib(pdev);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
> + if (!res)
> + platform_get_resource(pdev, IORESOURCE_MEM, 0);
> release_mem_region(res->start, SMC_IO_EXTENT);
>
> free_netdev(ndev);
> @@ -2195,9 +2263,7 @@
>
> if (ndev && level == RESUME_ENABLE) {
> struct smc_local *lp = netdev_priv(ndev);
> -
> - if (pdev->num_resources == 3)
> - smc_enable_device(pdev->resource[2].start);
> + smc_enable_device(pdev);
> if (netif_running(ndev)) {
> smc_reset(ndev);
> smc_enable(ndev);
> Index: 2.6/drivers/net/smc91x.h
> ===================================================================
> --- 2.6.orig/drivers/net/smc91x.h 2005-01-04 14:11:08.000000000 +0000
> +++ 2.6/drivers/net/smc91x.h 2005-01-25 14:47:42.000000000 +0000
> @@ -362,7 +362,7 @@
> #define SMC_IO_SHIFT 0
> #endif
> #define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
> -
> +#define SMC_DATA_EXTENT (4)
>
> /*
> . Bank Select Register:
> @@ -883,7 +883,7 @@
> #endif
>
> #if SMC_CAN_USE_32BIT
> -#define SMC_PUSH_DATA(p, l) \
> +#define _SMC_PUSH_DATA(p, l) \
> do { \
> char *__ptr = (p); \
> int __len = (l); \
> @@ -898,7 +898,7 @@
> SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> } \
> } while (0)
> -#define SMC_PULL_DATA(p, l) \
> +#define _SMC_PULL_DATA(p, l) \
> do { \
> char *__ptr = (p); \
> int __len = (l); \
> @@ -918,11 +918,11 @@
> SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
> } while (0)
> #elif SMC_CAN_USE_16BIT
> -#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
> -#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
> +#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
> +#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
> #elif SMC_CAN_USE_8BIT
> -#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
> -#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
> +#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
> +#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
> #endif
>
> #if ! SMC_CAN_USE_16BIT
> @@ -941,6 +941,51 @@
> })
> #endif
>
> +#if SMC_CAN_USE_DATACS
> +#define SMC_PUSH_DATA(p, l) \
> + if ( lp->datacs ) { \
> + unsigned char *__ptr = (p); \
> + int __len = (l); \
> + if (__len >= 2 && (unsigned long)__ptr & 2) { \
> + __len -= 2; \
> + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> + __ptr += 2; \
> + } \
> + outsl(lp->datacs, __ptr, __len >> 2); \
> + if (__len & 2) { \
> + __ptr += (__len & ~3); \
> + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> + } \
> + } else { \
> + _SMC_PUSH_DATA(p, l); \
> + }
> +
> +#define SMC_PULL_DATA(p, l) \
> + if ( lp->datacs ) { \
> + unsigned char *__ptr = (p); \
> + int __len = (l); \
> + if ((unsigned long)__ptr & 2) { \
> + /* \
> + * We want 32bit alignment here. \
> + * Since some buses perform a full 32bit \
> + * fetch even for 16bit data we can't use \
> + * SMC_inw() here. Back both source (on chip \
> + * and destination) pointers of 2 bytes. \
> + */ \
> + __ptr -= 2; \
> + __len += 2; \
> + SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
> + } \
> + __len += 2; \
> + insl( lp->datacs, __ptr, __len >> 2); \
> + } else { \
> + _SMC_PULL_DATA(p, l); \
> + }
> +#else
> +#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
> +#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
> +#endif
> +
> #if !defined (SMC_INTERRUPT_PREAMBLE)
> # define SMC_INTERRUPT_PREAMBLE
> #endif
> Index: 2.6/arch/arm/mach-sa1100/neponset.c
> ===================================================================
> --- 2.6.orig/arch/arm/mach-sa1100/neponset.c 2005-01-04 14:10:53.000000000 +0000
> +++ 2.6/arch/arm/mach-sa1100/neponset.c 2005-01-25 15:56:00.130447587 +0000
> @@ -266,6 +266,7 @@
>
> static struct resource smc91x_resources[] = {
> [0] = {
> + .name = "smc91x-regs",
> .start = SA1100_CS3_PHYS,
> .end = SA1100_CS3_PHYS + 0x01ffffff,
> .flags = IORESOURCE_MEM,
> @@ -276,6 +277,7 @@
> .flags = IORESOURCE_IRQ,
> },
> [2] = {
> + .name = "smc91x-attrib",
> .start = SA1100_CS3_PHYS + 0x02000000,
> .end = SA1100_CS3_PHYS + 0x03ffffff,
> .flags = IORESOURCE_MEM,
> Index: 2.6/arch/arm/mach-pxa/lubbock.c
> ===================================================================
> --- 2.6.orig/arch/arm/mach-pxa/lubbock.c 2005-01-04 14:10:53.000000000 +0000
> +++ 2.6/arch/arm/mach-pxa/lubbock.c 2005-01-25 15:56:00.048469724 +0000
> @@ -137,6 +137,7 @@
>
> static struct resource smc91x_resources[] = {
> [0] = {
> + .name = "smc91x-regs",
> .start = 0x0c000000,
> .end = 0x0c0fffff,
> .flags = IORESOURCE_MEM,
> @@ -147,6 +148,7 @@
> .flags = IORESOURCE_IRQ,
> },
> [2] = {
> + .name = "smc91x-attrib",
> .start = 0x0e000000,
> .end = 0x0e0fffff,
> .flags = IORESOURCE_MEM,
>
>
>
> --
> Ian Campbell, Senior Design Engineer
> Web: http://www.arcom.com
> Arcom, Clifton Road, Direct: +44 (0)1223 403 465
> Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200
>
>
> _____________________________________________________________________
> The message in this transmission is sent in confidence for the attention of the addressee only and should not be disclosed to any other party. Unauthorised recipients are requested to preserve this confidentiality. Please advise the sender if the addressee is not resident at the receiving end. Email to and from Arcom is automatically monitored for operational and lawful business reasons.
>
> This message has been virus scanned by MessageLabs.
>


Nicolas
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/