2 * drivers/can/h7202_can.c
6 * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
7 * - Simon Kallweit, intefo AG
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the version 2 of the GNU General Public License
11 * as published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/interrupt.h>
26 #include <linux/platform_device.h>
27 #include <linux/netdevice.h>
28 #include <linux/can.h>
29 #include <linux/can/dev.h>
30 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
35 #include <asm/hardware.h>
39 #define DRV_NAME "h7202can"
41 #define CAN_ENABLE 0x0e
43 static u16 h7202can_read_reg(struct net_device *dev, enum c_regs reg)
48 /* The big kernel lock is used to prevent any other AMBA devices from
49 * interfering with the current register read operation. The register
50 * is read twice because of braindamaged hynix cpu.
53 val = inw(dev->base_addr + (reg<<1));
54 for (i = 0; i < DELAY; i++);
55 val = inw(dev->base_addr + (reg<<1));
56 for (i = 0; i < DELAY; i++);
62 static void h7202can_write_reg(struct net_device *dev, enum c_regs reg, u16 val)
67 outw(val, dev->base_addr + (reg<<1));
68 for (i = 0; i < DELAY; i++);
72 static int h7202can_drv_probe(struct platform_device *pdev)
74 struct net_device *dev;
75 struct ccan_priv *priv;
80 dev = alloc_ccandev(sizeof(struct ccan_priv));
84 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
85 dev->irq = platform_get_irq(pdev, 0);
86 if (!mem || !dev->irq)
89 mem_size = mem->end - mem->start + 1;
90 if (!request_mem_region(mem->start, mem_size, pdev->dev.driver->name)) {
91 dev_err(&pdev->dev, "resource unavailable\n");
95 SET_NETDEV_DEV(dev, &pdev->dev);
97 dev->base_addr = (unsigned long)ioremap_nocache(mem->start, mem_size);
99 if (!dev->base_addr) {
100 dev_err(&pdev->dev, "failed to map can port\n");
105 priv = netdev_priv(dev);
106 priv->can.can_sys_clock = 8000000;
107 priv->read_reg = h7202can_read_reg;
108 priv->write_reg = h7202can_write_reg;
110 platform_set_drvdata(pdev, dev);
112 /* configure ports */
113 switch (mem->start) {
115 CPU_REG(GPIO_C_VIRT, GPIO_EN) &= ~(3<<1);
116 CPU_REG(GPIO_C_VIRT, GPIO_DIR) &= ~(1<<1);
117 CPU_REG(GPIO_C_VIRT, GPIO_DIR) |= (1<<2);
120 CPU_REG(GPIO_E_VIRT, GPIO_EN) &= ~(3<<16);
121 CPU_REG(GPIO_E_VIRT, GPIO_DIR) |= (1<<16);
122 CPU_REG(GPIO_E_VIRT, GPIO_DIR) &= ~(1<<17);
127 h7202can_write_reg(dev, CAN_ENABLE, 1);
129 ret = register_ccandev(dev);
131 dev_info(&pdev->dev, "probe for a port 0x%lX done\n",
136 iounmap((unsigned long *)dev->base_addr);
138 release_mem_region(mem->start, mem_size);
141 dev_err(&pdev->dev, "probe failed\n");
145 static int h7202can_drv_remove(struct platform_device *pdev)
147 struct net_device *dev = platform_get_drvdata(pdev);
148 struct resource *mem;
150 platform_set_drvdata(pdev, NULL);
151 unregister_ccandev(dev);
153 iounmap((volatile void __iomem *)(dev->base_addr));
154 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
155 release_mem_region(mem->start, mem->end - mem->start + 1);
161 static int h7202can_drv_suspend(struct platform_device *pdev,
167 static int h7202can_drv_resume(struct platform_device *pdev)
171 #endif /* CONFIG_PM */
173 static struct platform_driver h7202can_driver = {
177 .probe = h7202can_drv_probe,
178 .remove = h7202can_drv_remove,
180 .suspend = h7202can_drv_suspend,
181 .resume = h7202can_drv_resume,
182 #endif /* CONFIG_PM */
185 static int __init h7202can_init(void)
187 printk(KERN_INFO "%s initializing\n", h7202can_driver.driver.name);
188 return platform_driver_register(&h7202can_driver);
191 static void __exit h7202can_cleanup(void)
193 platform_driver_unregister(&h7202can_driver);
194 printk(KERN_INFO "%s unloaded\n", h7202can_driver.driver.name);
197 module_init(h7202can_init);
198 module_exit(h7202can_cleanup);
200 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
201 MODULE_AUTHOR("Simon Kallweit <simon.kallweit@intefo.ch>");
202 MODULE_LICENSE("GPL v2");
203 MODULE_DESCRIPTION("CAN port driver Hynix H7202 processor");