Commit | Line | Data |
---|---|---|
2b27bdcc | 1 | // SPDX-License-Identifier: GPL-2.0-only |
b63128e8 TL |
2 | /* |
3 | * Helper module for board specific I2C bus registration | |
4 | * | |
5 | * Copyright (C) 2009 Nokia Corporation. | |
b63128e8 TL |
6 | */ |
7 | ||
65fa3e71 | 8 | #include <linux/i2c.h> |
79fc540f | 9 | #include <linux/platform_data/i2c-omap.h> |
7e0a9e62 AB |
10 | |
11 | #include "mux.h" | |
e4c060db | 12 | #include "soc.h" |
e514f1fd | 13 | #include "i2c.h" |
b63128e8 | 14 | |
3a8761c0 TL |
15 | #define OMAP_I2C_SIZE 0x3f |
16 | #define OMAP1_I2C_BASE 0xfffb3800 | |
3a8761c0 TL |
17 | |
18 | static const char name[] = "omap_i2c"; | |
19 | ||
20 | static struct resource i2c_resources[2] = { | |
21 | }; | |
22 | ||
23 | static struct platform_device omap_i2c_devices[1] = { | |
24 | }; | |
25 | ||
26 | static void __init omap1_i2c_mux_pins(int bus_id) | |
b63128e8 | 27 | { |
8825acd7 AB |
28 | omap_cfg_reg(I2C_SDA); |
29 | omap_cfg_reg(I2C_SCL); | |
b63128e8 | 30 | } |
3a8761c0 TL |
31 | |
32 | int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata, | |
33 | int bus_id) | |
34 | { | |
35 | struct platform_device *pdev; | |
36 | struct resource *res; | |
37 | ||
c34f7c69 TL |
38 | if (bus_id > 1) |
39 | return -EINVAL; | |
40 | ||
3a8761c0 TL |
41 | omap1_i2c_mux_pins(bus_id); |
42 | ||
43 | pdev = &omap_i2c_devices[bus_id - 1]; | |
44 | pdev->id = bus_id; | |
45 | pdev->name = name; | |
46 | pdev->num_resources = ARRAY_SIZE(i2c_resources); | |
47 | res = i2c_resources; | |
48 | res[0].start = OMAP1_I2C_BASE; | |
49 | res[0].end = res[0].start + OMAP_I2C_SIZE; | |
50 | res[0].flags = IORESOURCE_MEM; | |
685e2d08 | 51 | res[1].start = INT_I2C; |
3a8761c0 TL |
52 | res[1].flags = IORESOURCE_IRQ; |
53 | pdev->resource = res; | |
54 | ||
55 | /* all OMAP1 have IP version 1 register set */ | |
56 | pdata->rev = OMAP_I2C_IP_VERSION_1; | |
57 | ||
58 | /* all OMAP1 I2C are implemented like this */ | |
59 | pdata->flags = OMAP_I2C_FLAG_NO_FIFO | | |
60 | OMAP_I2C_FLAG_SIMPLE_CLOCK | | |
61 | OMAP_I2C_FLAG_16BIT_DATA_REG | | |
62 | OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK; | |
63 | ||
64 | /* how the cpu bus is wired up differs for 7xx only */ | |
65 | ||
8825acd7 | 66 | pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2; |
3a8761c0 TL |
67 | |
68 | pdev->dev.platform_data = pdata; | |
69 | ||
70 | return platform_device_register(pdev); | |
71 | } | |
a6cf912c | 72 | |
65fa3e71 TL |
73 | #define OMAP_I2C_MAX_CONTROLLERS 4 |
74 | static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS]; | |
75 | ||
76 | #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) | |
77 | ||
78 | /** | |
79 | * omap_i2c_bus_setup - Process command line options for the I2C bus speed | |
80 | * @str: String of options | |
81 | * | |
82 | * This function allow to override the default I2C bus speed for given I2C | |
83 | * bus with a command line option. | |
84 | * | |
85 | * Format: i2c_bus=bus_id,clkrate (in kHz) | |
86 | * | |
87 | * Returns 1 on success, 0 otherwise. | |
88 | */ | |
89 | static int __init omap_i2c_bus_setup(char *str) | |
90 | { | |
91 | int ints[3]; | |
92 | ||
93 | get_options(str, 3, ints); | |
94 | if (ints[0] < 2 || ints[1] < 1 || | |
95 | ints[1] > OMAP_I2C_MAX_CONTROLLERS) | |
96 | return 0; | |
97 | i2c_pdata[ints[1] - 1].clkrate = ints[2]; | |
98 | i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; | |
99 | ||
100 | return 1; | |
101 | } | |
102 | __setup("i2c_bus=", omap_i2c_bus_setup); | |
103 | ||
104 | /* | |
105 | * Register busses defined in command line but that are not registered with | |
106 | * omap_register_i2c_bus from board initialization code. | |
107 | */ | |
108 | int __init omap_register_i2c_bus_cmdline(void) | |
109 | { | |
110 | int i, err = 0; | |
111 | ||
112 | for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) | |
113 | if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { | |
114 | i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; | |
115 | err = omap_i2c_add_bus(&i2c_pdata[i], i + 1); | |
116 | if (err) | |
117 | goto out; | |
118 | } | |
119 | ||
120 | out: | |
121 | return err; | |
122 | } | |
123 | ||
124 | /** | |
125 | * omap_register_i2c_bus - register I2C bus with device descriptors | |
126 | * @bus_id: bus id counting from number 1 | |
127 | * @clkrate: clock rate of the bus in kHz | |
128 | * @info: pointer into I2C device descriptor table or NULL | |
129 | * @len: number of descriptors in the table | |
130 | * | |
131 | * Returns 0 on success or an error code. | |
132 | */ | |
133 | int __init omap_register_i2c_bus(int bus_id, u32 clkrate, | |
134 | struct i2c_board_info const *info, | |
135 | unsigned len) | |
136 | { | |
137 | int err; | |
138 | ||
139 | BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS); | |
140 | ||
141 | if (info) { | |
142 | err = i2c_register_board_info(bus_id, info, len); | |
143 | if (err) | |
144 | return err; | |
145 | } | |
146 | ||
147 | if (!i2c_pdata[bus_id - 1].clkrate) | |
148 | i2c_pdata[bus_id - 1].clkrate = clkrate; | |
149 | ||
150 | i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; | |
151 | ||
152 | return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id); | |
153 | } | |
154 | ||
a6cf912c TL |
155 | static int __init omap_i2c_cmdline(void) |
156 | { | |
157 | return omap_register_i2c_bus_cmdline(); | |
158 | } | |
159 | subsys_initcall(omap_i2c_cmdline); |