#include <asm/arch/gpio.h>
+static void omap_nop_release(struct device *dev)
+{
+ /* Nothing */
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+
+#define OMAP_I2C_BASE 0xfffb3800
+
+static struct resource i2c_resources[] = {
+ {
+ .start = OMAP_I2C_BASE,
+ .end = OMAP_I2C_BASE + 0x3f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* DMA not used; works around erratum writing to non-empty i2c fifo */
+
+static struct platform_device omap_i2c_device = {
+ .name = "i2c_omap",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(i2c_resources),
+ .resource = i2c_resources,
+};
+
+static void omap_init_i2c(void)
+{
+ /* FIXME define and use a boot tag, in case of boards that
+ * either don't wire up I2C, or chips that mux it differently...
+ * it can include clocking and address info, maybe more.
+ */
+ omap_cfg_reg(I2C_SCL);
+ omap_cfg_reg(I2C_SDA);
+
+ (void) platform_device_register(&omap_i2c_device);
+}
+#else
+static inline void omap_init_i2c(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
static u64 irda_dmamask = 0xffffffff;
static inline void omap_init_irda(void) {}
#endif
-#if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC)
-
-#define OMAP_RTC_BASE 0xfffb4800
-
-static struct resource rtc_resources[] = {
- {
- .start = OMAP_RTC_BASE,
- .end = OMAP_RTC_BASE + 0x5f,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = INT_RTC_TIMER,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = INT_RTC_ALARM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device omap_rtc_device = {
- .name = "omap_rtc",
- .id = -1,
- .dev = {
- .release = omap_nop_release,
- },
- .num_resources = ARRAY_SIZE(rtc_resources),
- .resource = rtc_resources,
-};
-
-static void omap_init_rtc(void)
-{
- (void) platform_device_register(&omap_rtc_device);
-}
-#else
-static inline void omap_init_rtc(void) {}
-#endif
-
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
#define OMAP_MMC1_BASE 0xfffb7800
#define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */
-static void mmc_release(struct device *dev)
-{
- /* Nothing to release */
-}
-
static struct omap_mmc_conf mmc1_conf;
static u64 mmc1_dmamask = 0xffffffff;
.name = "mmci-omap",
.id = 1,
.dev = {
- .release = mmc_release,
+ .release = omap_nop_release,
.dma_mask = &mmc1_dmamask,
.platform_data = &mmc1_conf,
},
.name = "mmci-omap",
.id = 2,
.dev = {
- .release = mmc_release,
+ .release = omap_nop_release,
.dma_mask = &mmc2_dmamask,
.platform_data = &mmc2_conf,
},
static inline void omap_init_mmc(void) {}
#endif
+#if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC)
+
+#define OMAP_RTC_BASE 0xfffb4800
+
+static struct resource rtc_resources[] = {
+ {
+ .start = OMAP_RTC_BASE,
+ .end = OMAP_RTC_BASE + 0x5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_RTC_TIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device omap_rtc_device = {
+ .name = "omap_rtc",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static void omap_init_rtc(void)
+{
+ (void) platform_device_register(&omap_rtc_device);
+}
+#else
+static inline void omap_init_rtc(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#if defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE)
#define OMAP_WDT_BASE 0xfffeb000
*/
static int __init omap_init_devices(void)
{
- //omap_init_i2c();
+ /* please keep these calls, and their implementations above,
+ * in alphabetical order so they're easier to sort through.
+ */
+ omap_init_i2c();
omap_init_irda();
omap_init_mmc();
omap_init_rtc();
return IRQ_HANDLED;
}
-static int omap_i2c_remove(struct device *dev)
-{
- return 0;
-}
-
-static void omap_i2c_device_release(struct device *dev)
-{
- /* Nothing */
-}
-
static struct i2c_algorithm omap_i2c_algo = {
.name = "OMAP I2C algorithm",
.id = I2C_ALGO_EXP,
.algo = &omap_i2c_algo,
};
-static struct device_driver omap_i2c_driver = {
- .name = "omap_i2c",
- .bus = &platform_bus_type,
- .remove = omap_i2c_remove,
-};
-
-static struct platform_device omap_i2c_device = {
- .name = "i2c",
- .id = -1,
- .dev = {
- .driver = &omap_i2c_driver,
- .release = omap_i2c_device_release,
- },
-};
-
static int __init
-omap_i2c_init(void)
+omap_i2c_probe(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *mem;
int r;
- r = (int) request_mem_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE,
+ /* NOTE: driver uses the static register mapping */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ pr_debug("%s: no mem resource?\n", driver_name);
+ return -ENODEV;
+ }
+ r = (int) request_mem_region(mem->start, (mem->end - mem->start) + 1,
driver_name);
if (!r) {
pr_debug("%s: I2C region already claimed\n", driver_name);
memset(&omap_i2c_dev, 0, sizeof(omap_i2c_dev));
init_waitqueue_head(&omap_i2c_dev.cmd_wait);
+ /* reset ASAP, clearing any IRQs */
+ omap_i2c_reset();
+
r = request_irq(INT_I2C, omap_i2c_isr, 0, driver_name, &omap_i2c_dev);
if (r) {
pr_debug("%s: failure requesting irq\n", driver_name);
pr_info("%s: rev%d.%d at %d KHz\n", driver_name,
r >> 4, r & 0xf, clock);
+ /* i2c device drivers may be active on return from add_adapter() */
i2c_set_adapdata(&omap_i2c_adap, &omap_i2c_dev);
+ omap_i2c_adap.dev.parent = dev;
r = i2c_add_adapter(&omap_i2c_adap);
if (r) {
pr_debug("%s: failure adding adapter\n", driver_name);
goto do_free_irq;
}
- /* configure I/O pin multiplexing */
- /* FIXME: This should be done in bootloader */
- omap_cfg_reg(I2C_SCL);
- omap_cfg_reg(I2C_SDA);
-
- omap_i2c_reset();
-
- if(driver_register(&omap_i2c_driver) != 0)
- printk(KERN_ERR "Driver register failed for omap_i2c\n");
- if(platform_device_register(&omap_i2c_device) != 0) {
- printk(KERN_ERR "Device register failed for i2c\n");
- driver_unregister(&omap_i2c_driver);
- }
-
return 0;
do_free_irq:
free_irq(INT_I2C, &omap_i2c_dev);
do_release_region:
- release_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE);
+ writew(0, OMAP_I2C_CON);
+ release_mem_region(mem->start, (mem->end - mem->start) + 1);
return r;
}
static void __exit
-omap_i2c_exit(void)
+omap_i2c_remove(struct device *dev)
{
- i2c_del_adapter(&omap_i2c_adap);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *mem;
+
writew(0, OMAP_I2C_CON);
+ i2c_del_adapter(&omap_i2c_adap);
free_irq(INT_I2C, &omap_i2c_dev);
- release_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE);
- driver_unregister(&omap_i2c_driver);
- platform_device_unregister(&omap_i2c_device);
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, (mem->end - mem->start) + 1);
}
+static struct device_driver omap_i2c_driver = {
+ .name = (char *)driver_name,
+ .bus = &platform_bus_type,
+ .probe = omap_i2c_probe,
+ .remove = __exit_p(omap_i2c_remove),
+};
+
/* i2c may be needed to bring up other drivers */
-subsys_initcall(omap_i2c_init);
-module_exit(omap_i2c_exit);
+static int __init
+omap_i2c_init_driver(void)
+{
+ return driver_register(&omap_i2c_driver);
+}
+subsys_initcall(omap_i2c_init_driver);
+
+static void __exit omap_i2c_exit_driver(void)
+{
+ driver_unregister(&omap_i2c_driver);
+}
+module_exit(omap_i2c_exit_driver);
MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
MODULE_DESCRIPTION("TI OMAP I2C bus adapter");