]> Pileus Git - ~andy/linux/blob - arch/arm/mach-omap2/gpmc-smsc911x.c
5e5880d6d099e9a17e29436f7515f27ad2f94093
[~andy/linux] / arch / arm / mach-omap2 / gpmc-smsc911x.c
1 /*
2  * linux/arch/arm/mach-omap2/gpmc-smsc911x.c
3  *
4  * Copyright (C) 2009 Li-Pro.Net
5  * Stephan Linz <linz@li-pro.net>
6  *
7  * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.c
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 #define pr_fmt(fmt) "%s: " fmt, __func__
14
15 #include <linux/kernel.h>
16 #include <linux/platform_device.h>
17 #include <linux/gpio.h>
18 #include <linux/delay.h>
19 #include <linux/interrupt.h>
20 #include <linux/io.h>
21 #include <linux/smsc911x.h>
22 #include <linux/regulator/fixed.h>
23 #include <linux/regulator/machine.h>
24
25 #include <plat/board.h>
26 #include <plat/gpmc.h>
27 #include <plat/gpmc-smsc911x.h>
28
29 static struct omap_smsc911x_platform_data *gpmc_cfg;
30
31 static struct resource gpmc_smsc911x_resources[] = {
32         [0] = {
33                 .flags          = IORESOURCE_MEM,
34         },
35         [1] = {
36                 .flags          = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
37         },
38 };
39
40 static struct smsc911x_platform_config gpmc_smsc911x_config = {
41         .phy_interface  = PHY_INTERFACE_MODE_MII,
42         .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
43         .irq_type       = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
44         .flags          = SMSC911X_USE_16BIT,
45 };
46
47 static struct regulator_consumer_supply gpmc_smsc911x_supply[] = {
48         REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
49         REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
50 };
51
52 /* Generic regulator definition to satisfy smsc911x */
53 static struct regulator_init_data gpmc_smsc911x_reg_init_data = {
54         .constraints = {
55                 .min_uV                 = 3300000,
56                 .max_uV                 = 3300000,
57                 .valid_modes_mask       = REGULATOR_MODE_NORMAL
58                                         | REGULATOR_MODE_STANDBY,
59                 .valid_ops_mask         = REGULATOR_CHANGE_MODE
60                                         | REGULATOR_CHANGE_STATUS,
61         },
62         .num_consumer_supplies  = ARRAY_SIZE(gpmc_smsc911x_supply),
63         .consumer_supplies      = gpmc_smsc911x_supply,
64 };
65
66 static struct fixed_voltage_config gpmc_smsc911x_fixed_reg_data = {
67         .supply_name            = "gpmc_smsc911x",
68         .microvolts             = 3300000,
69         .gpio                   = -EINVAL,
70         .startup_delay          = 0,
71         .enable_high            = 0,
72         .enabled_at_boot        = 1,
73         .init_data              = &gpmc_smsc911x_reg_init_data,
74 };
75
76 /*
77  * Platform device id of 42 is a temporary fix to avoid conflicts
78  * with other reg-fixed-voltage devices. The real fix should
79  * involve the driver core providing a way of dynamically
80  * assigning a unique id on registration for platform devices
81  * in the same name space.
82  */
83 static struct platform_device gpmc_smsc911x_regulator = {
84         .name           = "reg-fixed-voltage",
85         .id             = 42,
86         .dev = {
87                 .platform_data  = &gpmc_smsc911x_fixed_reg_data,
88         },
89 };
90
91 /*
92  * Initialize smsc911x device connected to the GPMC. Note that we
93  * assume that pin multiplexing is done in the board-*.c file,
94  * or in the bootloader.
95  */
96 void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
97 {
98         struct platform_device *pdev;
99         unsigned long cs_mem_base;
100         int ret;
101
102         gpmc_cfg = board_data;
103
104         if (!gpmc_cfg->id) {
105                 ret = platform_device_register(&gpmc_smsc911x_regulator);
106                 if (ret < 0) {
107                         pr_err("Unable to register smsc911x regulators: %d\n",
108                                ret);
109                         return;
110                 }
111         }
112
113         if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
114                 pr_err("Failed to request GPMC mem region\n");
115                 return;
116         }
117
118         gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
119         gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
120
121         if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
122                 pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
123                 goto free1;
124         }
125
126         gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
127
128         if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
129                 ret = gpio_request_one(gpmc_cfg->gpio_reset,
130                                        GPIOF_OUT_INIT_HIGH, "smsc911x reset");
131                 if (ret) {
132                         pr_err("Failed to request reset GPIO%d\n",
133                                gpmc_cfg->gpio_reset);
134                         goto free2;
135                 }
136
137                 gpio_set_value(gpmc_cfg->gpio_reset, 0);
138                 msleep(100);
139                 gpio_set_value(gpmc_cfg->gpio_reset, 1);
140         }
141
142         if (gpmc_cfg->flags)
143                 gpmc_smsc911x_config.flags = gpmc_cfg->flags;
144
145         pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
146                  gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
147                  &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
148         if (!pdev) {
149                 pr_err("Unable to register platform device\n");
150                 gpio_free(gpmc_cfg->gpio_reset);
151                 goto free2;
152         }
153
154         return;
155
156 free2:
157         gpio_free(gpmc_cfg->gpio_irq);
158 free1:
159         gpmc_cs_free(gpmc_cfg->cs);
160
161         pr_err("Could not initialize smsc911x device\n");
162 }