diff options
54 files changed, 3670 insertions, 500 deletions
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 48da5fdcb9f1..b045fe54986a 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt | |||
@@ -228,3 +228,22 @@ is the corresponding frequency table helper for the ->target | |||
228 | stage. Just pass the values to this function, and the unsigned int | 228 | stage. Just pass the values to this function, and the unsigned int |
229 | index returns the number of the frequency table entry which contains | 229 | index returns the number of the frequency table entry which contains |
230 | the frequency the CPU shall be set to. | 230 | the frequency the CPU shall be set to. |
231 | |||
232 | The following macros can be used as iterators over cpufreq_frequency_table: | ||
233 | |||
234 | cpufreq_for_each_entry(pos, table) - iterates over all entries of frequency | ||
235 | table. | ||
236 | |||
237 | cpufreq-for_each_valid_entry(pos, table) - iterates over all entries, | ||
238 | excluding CPUFREQ_ENTRY_INVALID frequencies. | ||
239 | Use arguments "pos" - a cpufreq_frequency_table * as a loop cursor and | ||
240 | "table" - the cpufreq_frequency_table * you want to iterate over. | ||
241 | |||
242 | For example: | ||
243 | |||
244 | struct cpufreq_frequency_table *pos, *driver_freq_table; | ||
245 | |||
246 | cpufreq_for_each_entry(pos, driver_freq_table) { | ||
247 | /* Do something with pos */ | ||
248 | pos->frequency = ... | ||
249 | } | ||
diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt index 1413f39912d3..8aba48821a85 100644 --- a/Documentation/devicetree/bindings/mfd/mc13xxx.txt +++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt | |||
@@ -10,6 +10,9 @@ Optional properties: | |||
10 | - fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used | 10 | - fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used |
11 | 11 | ||
12 | Sub-nodes: | 12 | Sub-nodes: |
13 | - codec: Contain the Audio Codec node. | ||
14 | - adc-port: Contain PMIC SSI port number used for ADC. | ||
15 | - dac-port: Contain PMIC SSI port number used for DAC. | ||
13 | - leds : Contain the led nodes and initial register values in property | 16 | - leds : Contain the led nodes and initial register values in property |
14 | "led-control". Number of register depends of used IC, for MC13783 is 6, | 17 | "led-control". Number of register depends of used IC, for MC13783 is 6, |
15 | for MC13892 is 4, for MC34708 is 1. See datasheet for bits definitions of | 18 | for MC13892 is 4, for MC34708 is 1. See datasheet for bits definitions of |
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 85399c98f84a..45ce065e7170 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c | |||
@@ -1092,20 +1092,21 @@ int da850_register_cpufreq(char *async_clk) | |||
1092 | 1092 | ||
1093 | static int da850_round_armrate(struct clk *clk, unsigned long rate) | 1093 | static int da850_round_armrate(struct clk *clk, unsigned long rate) |
1094 | { | 1094 | { |
1095 | int i, ret = 0, diff; | 1095 | int ret = 0, diff; |
1096 | unsigned int best = (unsigned int) -1; | 1096 | unsigned int best = (unsigned int) -1; |
1097 | struct cpufreq_frequency_table *table = cpufreq_info.freq_table; | 1097 | struct cpufreq_frequency_table *table = cpufreq_info.freq_table; |
1098 | struct cpufreq_frequency_table *pos; | ||
1098 | 1099 | ||
1099 | rate /= 1000; /* convert to kHz */ | 1100 | rate /= 1000; /* convert to kHz */ |
1100 | 1101 | ||
1101 | for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { | 1102 | cpufreq_for_each_entry(pos, table) { |
1102 | diff = table[i].frequency - rate; | 1103 | diff = pos->frequency - rate; |
1103 | if (diff < 0) | 1104 | if (diff < 0) |
1104 | diff = -diff; | 1105 | diff = -diff; |
1105 | 1106 | ||
1106 | if (diff < best) { | 1107 | if (diff < best) { |
1107 | best = diff; | 1108 | best = diff; |
1108 | ret = table[i].frequency; | 1109 | ret = pos->frequency; |
1109 | } | 1110 | } |
1110 | } | 1111 | } |
1111 | 1112 | ||
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index 615e5b1fb025..6bf626700557 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c | |||
@@ -46,15 +46,8 @@ | |||
46 | 46 | ||
47 | static bool is_offset_valid; | 47 | static bool is_offset_valid; |
48 | static u8 smps_offset; | 48 | static u8 smps_offset; |
49 | /* | ||
50 | * Flag to ensure Smartreflex bit in TWL | ||
51 | * being cleared in board file is not overwritten. | ||
52 | */ | ||
53 | static bool __initdata twl_sr_enable_autoinit; | ||
54 | 49 | ||
55 | #define TWL4030_DCDC_GLOBAL_CFG 0x06 | ||
56 | #define REG_SMPS_OFFSET 0xE0 | 50 | #define REG_SMPS_OFFSET 0xE0 |
57 | #define SMARTREFLEX_ENABLE BIT(3) | ||
58 | 51 | ||
59 | static unsigned long twl4030_vsel_to_uv(const u8 vsel) | 52 | static unsigned long twl4030_vsel_to_uv(const u8 vsel) |
60 | { | 53 | { |
@@ -251,18 +244,6 @@ int __init omap3_twl_init(void) | |||
251 | if (!cpu_is_omap34xx()) | 244 | if (!cpu_is_omap34xx()) |
252 | return -ENODEV; | 245 | return -ENODEV; |
253 | 246 | ||
254 | /* | ||
255 | * The smartreflex bit on twl4030 specifies if the setting of voltage | ||
256 | * is done over the I2C_SR path. Since this setting is independent of | ||
257 | * the actual usage of smartreflex AVS module, we enable TWL SR bit | ||
258 | * by default irrespective of whether smartreflex AVS module is enabled | ||
259 | * on the OMAP side or not. This is because without this bit enabled, | ||
260 | * the voltage scaling through vp forceupdate/bypass mechanism of | ||
261 | * voltage scaling will not function on TWL over I2C_SR. | ||
262 | */ | ||
263 | if (!twl_sr_enable_autoinit) | ||
264 | omap3_twl_set_sr_bit(true); | ||
265 | |||
266 | voltdm = voltdm_lookup("mpu_iva"); | 247 | voltdm = voltdm_lookup("mpu_iva"); |
267 | omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic); | 248 | omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic); |
268 | 249 | ||
@@ -271,44 +252,3 @@ int __init omap3_twl_init(void) | |||
271 | 252 | ||
272 | return 0; | 253 | return 0; |
273 | } | 254 | } |
274 | |||
275 | /** | ||
276 | * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL | ||
277 | * @enable: enable SR mode in twl or not | ||
278 | * | ||
279 | * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure | ||
280 | * voltage scaling through OMAP SR works. Else, the smartreflex bit | ||
281 | * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but | ||
282 | * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct | ||
283 | * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages, | ||
284 | * in those scenarios this bit is to be cleared (enable = false). | ||
285 | * | ||
286 | * Returns 0 on success, error is returned if I2C read/write fails. | ||
287 | */ | ||
288 | int __init omap3_twl_set_sr_bit(bool enable) | ||
289 | { | ||
290 | u8 temp; | ||
291 | int ret; | ||
292 | if (twl_sr_enable_autoinit) | ||
293 | pr_warning("%s: unexpected multiple calls\n", __func__); | ||
294 | |||
295 | ret = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp, | ||
296 | TWL4030_DCDC_GLOBAL_CFG); | ||
297 | if (ret) | ||
298 | goto err; | ||
299 | |||
300 | if (enable) | ||
301 | temp |= SMARTREFLEX_ENABLE; | ||
302 | else | ||
303 | temp &= ~SMARTREFLEX_ENABLE; | ||
304 | |||
305 | ret = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp, | ||
306 | TWL4030_DCDC_GLOBAL_CFG); | ||
307 | if (!ret) { | ||
308 | twl_sr_enable_autoinit = true; | ||
309 | return 0; | ||
310 | } | ||
311 | err: | ||
312 | pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret); | ||
313 | return ret; | ||
314 | } | ||
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 000e4e0afd7e..b0c18ed8d83f 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -213,7 +213,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) | |||
213 | 213 | ||
214 | static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) | 214 | static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) |
215 | { | 215 | { |
216 | int i; | 216 | struct cpufreq_frequency_table *pos; |
217 | struct acpi_processor_performance *perf; | 217 | struct acpi_processor_performance *perf; |
218 | 218 | ||
219 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) | 219 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) |
@@ -223,10 +223,9 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) | |||
223 | 223 | ||
224 | perf = data->acpi_data; | 224 | perf = data->acpi_data; |
225 | 225 | ||
226 | for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | 226 | cpufreq_for_each_entry(pos, data->freq_table) |
227 | if (msr == perf->states[data->freq_table[i].driver_data].status) | 227 | if (msr == perf->states[pos->driver_data].status) |
228 | return data->freq_table[i].frequency; | 228 | return pos->frequency; |
229 | } | ||
230 | return data->freq_table[0].frequency; | 229 | return data->freq_table[0].frequency; |
231 | } | 230 | } |
232 | 231 | ||
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index bad2ed317ba2..1f4d4e315057 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c | |||
@@ -226,22 +226,22 @@ static inline u32 get_table_count(struct cpufreq_frequency_table *table) | |||
226 | /* get the minimum frequency in the cpufreq_frequency_table */ | 226 | /* get the minimum frequency in the cpufreq_frequency_table */ |
227 | static inline u32 get_table_min(struct cpufreq_frequency_table *table) | 227 | static inline u32 get_table_min(struct cpufreq_frequency_table *table) |
228 | { | 228 | { |
229 | int i; | 229 | struct cpufreq_frequency_table *pos; |
230 | uint32_t min_freq = ~0; | 230 | uint32_t min_freq = ~0; |
231 | for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) | 231 | cpufreq_for_each_entry(pos, table) |
232 | if (table[i].frequency < min_freq) | 232 | if (pos->frequency < min_freq) |
233 | min_freq = table[i].frequency; | 233 | min_freq = pos->frequency; |
234 | return min_freq; | 234 | return min_freq; |
235 | } | 235 | } |
236 | 236 | ||
237 | /* get the maximum frequency in the cpufreq_frequency_table */ | 237 | /* get the maximum frequency in the cpufreq_frequency_table */ |
238 | static inline u32 get_table_max(struct cpufreq_frequency_table *table) | 238 | static inline u32 get_table_max(struct cpufreq_frequency_table *table) |
239 | { | 239 | { |
240 | int i; | 240 | struct cpufreq_frequency_table *pos; |
241 | uint32_t max_freq = 0; | 241 | uint32_t max_freq = 0; |
242 | for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) | 242 | cpufreq_for_each_entry(pos, table) |
243 | if (table[i].frequency > max_freq) | 243 | if (pos->frequency > max_freq) |
244 | max_freq = table[i].frequency; | 244 | max_freq = pos->frequency; |
245 | return max_freq; | 245 | return max_freq; |
246 | } | 246 | } |
247 | 247 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index abda6609d3e7..a517da996aaf 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -237,6 +237,17 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy) | |||
237 | } | 237 | } |
238 | EXPORT_SYMBOL_GPL(cpufreq_cpu_put); | 238 | EXPORT_SYMBOL_GPL(cpufreq_cpu_put); |
239 | 239 | ||
240 | bool cpufreq_next_valid(struct cpufreq_frequency_table **pos) | ||
241 | { | ||
242 | while ((*pos)->frequency != CPUFREQ_TABLE_END) | ||
243 | if ((*pos)->frequency != CPUFREQ_ENTRY_INVALID) | ||
244 | return true; | ||
245 | else | ||
246 | (*pos)++; | ||
247 | return false; | ||
248 | } | ||
249 | EXPORT_SYMBOL_GPL(cpufreq_next_valid); | ||
250 | |||
240 | /********************************************************************* | 251 | /********************************************************************* |
241 | * EXTERNALLY AFFECTING FREQUENCY CHANGES * | 252 | * EXTERNALLY AFFECTING FREQUENCY CHANGES * |
242 | *********************************************************************/ | 253 | *********************************************************************/ |
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index ecaaebf969fc..0cd9b4dcef99 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -182,11 +182,11 @@ static void cpufreq_stats_free_table(unsigned int cpu) | |||
182 | 182 | ||
183 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | 183 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) |
184 | { | 184 | { |
185 | unsigned int i, j, count = 0, ret = 0; | 185 | unsigned int i, count = 0, ret = 0; |
186 | struct cpufreq_stats *stat; | 186 | struct cpufreq_stats *stat; |
187 | unsigned int alloc_size; | 187 | unsigned int alloc_size; |
188 | unsigned int cpu = policy->cpu; | 188 | unsigned int cpu = policy->cpu; |
189 | struct cpufreq_frequency_table *table; | 189 | struct cpufreq_frequency_table *pos, *table; |
190 | 190 | ||
191 | table = cpufreq_frequency_get_table(cpu); | 191 | table = cpufreq_frequency_get_table(cpu); |
192 | if (unlikely(!table)) | 192 | if (unlikely(!table)) |
@@ -205,12 +205,8 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | |||
205 | stat->cpu = cpu; | 205 | stat->cpu = cpu; |
206 | per_cpu(cpufreq_stats_table, cpu) = stat; | 206 | per_cpu(cpufreq_stats_table, cpu) = stat; |
207 | 207 | ||
208 | for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { | 208 | cpufreq_for_each_valid_entry(pos, table) |
209 | unsigned int freq = table[i].frequency; | ||
210 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
211 | continue; | ||
212 | count++; | 209 | count++; |
213 | } | ||
214 | 210 | ||
215 | alloc_size = count * sizeof(int) + count * sizeof(u64); | 211 | alloc_size = count * sizeof(int) + count * sizeof(u64); |
216 | 212 | ||
@@ -228,15 +224,11 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | |||
228 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 224 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
229 | stat->trans_table = stat->freq_table + count; | 225 | stat->trans_table = stat->freq_table + count; |
230 | #endif | 226 | #endif |
231 | j = 0; | 227 | i = 0; |
232 | for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { | 228 | cpufreq_for_each_valid_entry(pos, table) |
233 | unsigned int freq = table[i].frequency; | 229 | if (freq_table_get_index(stat, pos->frequency) == -1) |
234 | if (freq == CPUFREQ_ENTRY_INVALID) | 230 | stat->freq_table[i++] = pos->frequency; |
235 | continue; | 231 | stat->state_num = i; |
236 | if (freq_table_get_index(stat, freq) == -1) | ||
237 | stat->freq_table[j++] = freq; | ||
238 | } | ||
239 | stat->state_num = j; | ||
240 | spin_lock(&cpufreq_stats_lock); | 232 | spin_lock(&cpufreq_stats_lock); |
241 | stat->last_time = get_jiffies_64(); | 233 | stat->last_time = get_jiffies_64(); |
242 | stat->last_index = freq_table_get_index(stat, policy->cur); | 234 | stat->last_index = freq_table_get_index(stat, policy->cur); |
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 412a78bb0c94..4bebc1b5db48 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c | |||
@@ -45,7 +45,7 @@ static struct cpufreq_driver dbx500_cpufreq_driver = { | |||
45 | 45 | ||
46 | static int dbx500_cpufreq_probe(struct platform_device *pdev) | 46 | static int dbx500_cpufreq_probe(struct platform_device *pdev) |
47 | { | 47 | { |
48 | int i = 0; | 48 | struct cpufreq_frequency_table *pos; |
49 | 49 | ||
50 | freq_table = dev_get_platdata(&pdev->dev); | 50 | freq_table = dev_get_platdata(&pdev->dev); |
51 | if (!freq_table) { | 51 | if (!freq_table) { |
@@ -60,10 +60,8 @@ static int dbx500_cpufreq_probe(struct platform_device *pdev) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | pr_info("dbx500-cpufreq: Available frequencies:\n"); | 62 | pr_info("dbx500-cpufreq: Available frequencies:\n"); |
63 | while (freq_table[i].frequency != CPUFREQ_TABLE_END) { | 63 | cpufreq_for_each_entry(pos, freq_table) |
64 | pr_info(" %d Mhz\n", freq_table[i].frequency/1000); | 64 | pr_info(" %d Mhz\n", pos->frequency / 1000); |
65 | i++; | ||
66 | } | ||
67 | 65 | ||
68 | return cpufreq_register_driver(&dbx500_cpufreq_driver); | 66 | return cpufreq_register_driver(&dbx500_cpufreq_driver); |
69 | } | 67 | } |
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 7f5d2a68c353..1c06e786c9ba 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c | |||
@@ -147,7 +147,7 @@ static int elanfreq_target(struct cpufreq_policy *policy, | |||
147 | static int elanfreq_cpu_init(struct cpufreq_policy *policy) | 147 | static int elanfreq_cpu_init(struct cpufreq_policy *policy) |
148 | { | 148 | { |
149 | struct cpuinfo_x86 *c = &cpu_data(0); | 149 | struct cpuinfo_x86 *c = &cpu_data(0); |
150 | unsigned int i; | 150 | struct cpufreq_frequency_table *pos; |
151 | 151 | ||
152 | /* capability check */ | 152 | /* capability check */ |
153 | if ((c->x86_vendor != X86_VENDOR_AMD) || | 153 | if ((c->x86_vendor != X86_VENDOR_AMD) || |
@@ -159,10 +159,9 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) | |||
159 | max_freq = elanfreq_get_cpu_frequency(0); | 159 | max_freq = elanfreq_get_cpu_frequency(0); |
160 | 160 | ||
161 | /* table init */ | 161 | /* table init */ |
162 | for (i = 0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { | 162 | cpufreq_for_each_entry(pos, elanfreq_table) |
163 | if (elanfreq_table[i].frequency > max_freq) | 163 | if (pos->frequency > max_freq) |
164 | elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID; | 164 | pos->frequency = CPUFREQ_ENTRY_INVALID; |
165 | } | ||
166 | 165 | ||
167 | /* cpuinfo and default policy values */ | 166 | /* cpuinfo and default policy values */ |
168 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 167 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index f99cfe24e7bc..9c132550d910 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c | |||
@@ -29,17 +29,16 @@ static unsigned int locking_frequency; | |||
29 | static int exynos_cpufreq_get_index(unsigned int freq) | 29 | static int exynos_cpufreq_get_index(unsigned int freq) |
30 | { | 30 | { |
31 | struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; | 31 | struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; |
32 | int index; | 32 | struct cpufreq_frequency_table *pos; |
33 | 33 | ||
34 | for (index = 0; | 34 | cpufreq_for_each_entry(pos, freq_table) |
35 | freq_table[index].frequency != CPUFREQ_TABLE_END; index++) | 35 | if (pos->frequency == freq) |
36 | if (freq_table[index].frequency == freq) | ||
37 | break; | 36 | break; |
38 | 37 | ||
39 | if (freq_table[index].frequency == CPUFREQ_TABLE_END) | 38 | if (pos->frequency == CPUFREQ_TABLE_END) |
40 | return -EINVAL; | 39 | return -EINVAL; |
41 | 40 | ||
42 | return index; | 41 | return pos - freq_table; |
43 | } | 42 | } |
44 | 43 | ||
45 | static int exynos_cpufreq_scale(unsigned int target_freq) | 44 | static int exynos_cpufreq_scale(unsigned int target_freq) |
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index a6b8214d7b77..f33f25b483ca 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c | |||
@@ -114,25 +114,23 @@ static struct cpufreq_freqs freqs; | |||
114 | 114 | ||
115 | static int init_div_table(void) | 115 | static int init_div_table(void) |
116 | { | 116 | { |
117 | struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table; | 117 | struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table; |
118 | unsigned int tmp, clk_div, ema_div, freq, volt_id; | 118 | unsigned int tmp, clk_div, ema_div, freq, volt_id; |
119 | int i = 0; | ||
120 | struct dev_pm_opp *opp; | 119 | struct dev_pm_opp *opp; |
121 | 120 | ||
122 | rcu_read_lock(); | 121 | rcu_read_lock(); |
123 | for (i = 0; freq_tbl[i].frequency != CPUFREQ_TABLE_END; i++) { | 122 | cpufreq_for_each_entry(pos, freq_tbl) { |
124 | |||
125 | opp = dev_pm_opp_find_freq_exact(dvfs_info->dev, | 123 | opp = dev_pm_opp_find_freq_exact(dvfs_info->dev, |
126 | freq_tbl[i].frequency * 1000, true); | 124 | pos->frequency * 1000, true); |
127 | if (IS_ERR(opp)) { | 125 | if (IS_ERR(opp)) { |
128 | rcu_read_unlock(); | 126 | rcu_read_unlock(); |
129 | dev_err(dvfs_info->dev, | 127 | dev_err(dvfs_info->dev, |
130 | "failed to find valid OPP for %u KHZ\n", | 128 | "failed to find valid OPP for %u KHZ\n", |
131 | freq_tbl[i].frequency); | 129 | pos->frequency); |
132 | return PTR_ERR(opp); | 130 | return PTR_ERR(opp); |
133 | } | 131 | } |
134 | 132 | ||
135 | freq = freq_tbl[i].frequency / 1000; /* In MHZ */ | 133 | freq = pos->frequency / 1000; /* In MHZ */ |
136 | clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK) | 134 | clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK) |
137 | << P0_7_CPUCLKDEV_SHIFT; | 135 | << P0_7_CPUCLKDEV_SHIFT; |
138 | clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK) | 136 | clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK) |
@@ -157,7 +155,8 @@ static int init_div_table(void) | |||
157 | tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT) | 155 | tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT) |
158 | | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT)); | 156 | | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT)); |
159 | 157 | ||
160 | __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * i); | 158 | __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * |
159 | (pos - freq_tbl)); | ||
161 | } | 160 | } |
162 | 161 | ||
163 | rcu_read_unlock(); | 162 | rcu_read_unlock(); |
@@ -166,8 +165,9 @@ static int init_div_table(void) | |||
166 | 165 | ||
167 | static void exynos_enable_dvfs(unsigned int cur_frequency) | 166 | static void exynos_enable_dvfs(unsigned int cur_frequency) |
168 | { | 167 | { |
169 | unsigned int tmp, i, cpu; | 168 | unsigned int tmp, cpu; |
170 | struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table; | 169 | struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table; |
170 | struct cpufreq_frequency_table *pos; | ||
171 | /* Disable DVFS */ | 171 | /* Disable DVFS */ |
172 | __raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL); | 172 | __raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL); |
173 | 173 | ||
@@ -182,15 +182,15 @@ static void exynos_enable_dvfs(unsigned int cur_frequency) | |||
182 | __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN); | 182 | __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN); |
183 | 183 | ||
184 | /* Set initial performance index */ | 184 | /* Set initial performance index */ |
185 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 185 | cpufreq_for_each_entry(pos, freq_table) |
186 | if (freq_table[i].frequency == cur_frequency) | 186 | if (pos->frequency == cur_frequency) |
187 | break; | 187 | break; |
188 | 188 | ||
189 | if (freq_table[i].frequency == CPUFREQ_TABLE_END) { | 189 | if (pos->frequency == CPUFREQ_TABLE_END) { |
190 | dev_crit(dvfs_info->dev, "Boot up frequency not supported\n"); | 190 | dev_crit(dvfs_info->dev, "Boot up frequency not supported\n"); |
191 | /* Assign the highest frequency */ | 191 | /* Assign the highest frequency */ |
192 | i = 0; | 192 | pos = freq_table; |
193 | cur_frequency = freq_table[i].frequency; | 193 | cur_frequency = pos->frequency; |
194 | } | 194 | } |
195 | 195 | ||
196 | dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ", | 196 | dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ", |
@@ -199,7 +199,7 @@ static void exynos_enable_dvfs(unsigned int cur_frequency) | |||
199 | for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) { | 199 | for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) { |
200 | tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); | 200 | tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); |
201 | tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT); | 201 | tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT); |
202 | tmp |= (i << C0_3_PSTATE_NEW_SHIFT); | 202 | tmp |= ((pos - freq_table) << C0_3_PSTATE_NEW_SHIFT); |
203 | __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); | 203 | __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 08e7bbcf6d73..8e518c689393 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c | |||
@@ -21,22 +21,19 @@ | |||
21 | int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, | 21 | int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, |
22 | struct cpufreq_frequency_table *table) | 22 | struct cpufreq_frequency_table *table) |
23 | { | 23 | { |
24 | struct cpufreq_frequency_table *pos; | ||
24 | unsigned int min_freq = ~0; | 25 | unsigned int min_freq = ~0; |
25 | unsigned int max_freq = 0; | 26 | unsigned int max_freq = 0; |
26 | unsigned int i; | 27 | unsigned int freq; |
27 | 28 | ||
28 | for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { | 29 | cpufreq_for_each_valid_entry(pos, table) { |
29 | unsigned int freq = table[i].frequency; | 30 | freq = pos->frequency; |
30 | if (freq == CPUFREQ_ENTRY_INVALID) { | ||
31 | pr_debug("table entry %u is invalid, skipping\n", i); | ||
32 | 31 | ||
33 | continue; | ||
34 | } | ||
35 | if (!cpufreq_boost_enabled() | 32 | if (!cpufreq_boost_enabled() |
36 | && (table[i].flags & CPUFREQ_BOOST_FREQ)) | 33 | && (pos->flags & CPUFREQ_BOOST_FREQ)) |
37 | continue; | 34 | continue; |
38 | 35 | ||
39 | pr_debug("table entry %u: %u kHz\n", i, freq); | 36 | pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq); |
40 | if (freq < min_freq) | 37 | if (freq < min_freq) |
41 | min_freq = freq; | 38 | min_freq = freq; |
42 | if (freq > max_freq) | 39 | if (freq > max_freq) |
@@ -57,7 +54,8 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); | |||
57 | int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, | 54 | int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, |
58 | struct cpufreq_frequency_table *table) | 55 | struct cpufreq_frequency_table *table) |
59 | { | 56 | { |
60 | unsigned int next_larger = ~0, freq, i = 0; | 57 | struct cpufreq_frequency_table *pos; |
58 | unsigned int freq, next_larger = ~0; | ||
61 | bool found = false; | 59 | bool found = false; |
62 | 60 | ||
63 | pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", | 61 | pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", |
@@ -65,9 +63,9 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, | |||
65 | 63 | ||
66 | cpufreq_verify_within_cpu_limits(policy); | 64 | cpufreq_verify_within_cpu_limits(policy); |
67 | 65 | ||
68 | for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) { | 66 | cpufreq_for_each_valid_entry(pos, table) { |
69 | if (freq == CPUFREQ_ENTRY_INVALID) | 67 | freq = pos->frequency; |
70 | continue; | 68 | |
71 | if ((freq >= policy->min) && (freq <= policy->max)) { | 69 | if ((freq >= policy->min) && (freq <= policy->max)) { |
72 | found = true; | 70 | found = true; |
73 | break; | 71 | break; |
@@ -118,7 +116,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | |||
118 | .driver_data = ~0, | 116 | .driver_data = ~0, |
119 | .frequency = 0, | 117 | .frequency = 0, |
120 | }; | 118 | }; |
121 | unsigned int i; | 119 | struct cpufreq_frequency_table *pos; |
120 | unsigned int freq, i = 0; | ||
122 | 121 | ||
123 | pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", | 122 | pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", |
124 | target_freq, relation, policy->cpu); | 123 | target_freq, relation, policy->cpu); |
@@ -132,10 +131,10 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | |||
132 | break; | 131 | break; |
133 | } | 132 | } |
134 | 133 | ||
135 | for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { | 134 | cpufreq_for_each_valid_entry(pos, table) { |
136 | unsigned int freq = table[i].frequency; | 135 | freq = pos->frequency; |
137 | if (freq == CPUFREQ_ENTRY_INVALID) | 136 | |
138 | continue; | 137 | i = pos - table; |
139 | if ((freq < policy->min) || (freq > policy->max)) | 138 | if ((freq < policy->min) || (freq > policy->max)) |
140 | continue; | 139 | continue; |
141 | switch (relation) { | 140 | switch (relation) { |
@@ -184,8 +183,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); | |||
184 | int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, | 183 | int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, |
185 | unsigned int freq) | 184 | unsigned int freq) |
186 | { | 185 | { |
187 | struct cpufreq_frequency_table *table; | 186 | struct cpufreq_frequency_table *pos, *table; |
188 | int i; | ||
189 | 187 | ||
190 | table = cpufreq_frequency_get_table(policy->cpu); | 188 | table = cpufreq_frequency_get_table(policy->cpu); |
191 | if (unlikely(!table)) { | 189 | if (unlikely(!table)) { |
@@ -193,10 +191,9 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, | |||
193 | return -ENOENT; | 191 | return -ENOENT; |
194 | } | 192 | } |
195 | 193 | ||
196 | for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { | 194 | cpufreq_for_each_valid_entry(pos, table) |
197 | if (table[i].frequency == freq) | 195 | if (pos->frequency == freq) |
198 | return i; | 196 | return pos - table; |
199 | } | ||
200 | 197 | ||
201 | return -EINVAL; | 198 | return -EINVAL; |
202 | } | 199 | } |
@@ -208,16 +205,13 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); | |||
208 | static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, | 205 | static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, |
209 | bool show_boost) | 206 | bool show_boost) |
210 | { | 207 | { |
211 | unsigned int i = 0; | ||
212 | ssize_t count = 0; | 208 | ssize_t count = 0; |
213 | struct cpufreq_frequency_table *table = policy->freq_table; | 209 | struct cpufreq_frequency_table *pos, *table = policy->freq_table; |
214 | 210 | ||
215 | if (!table) | 211 | if (!table) |
216 | return -ENODEV; | 212 | return -ENODEV; |
217 | 213 | ||
218 | for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { | 214 | cpufreq_for_each_valid_entry(pos, table) { |
219 | if (table[i].frequency == CPUFREQ_ENTRY_INVALID) | ||
220 | continue; | ||
221 | /* | 215 | /* |
222 | * show_boost = true and driver_data = BOOST freq | 216 | * show_boost = true and driver_data = BOOST freq |
223 | * display BOOST freqs | 217 | * display BOOST freqs |
@@ -229,10 +223,10 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, | |||
229 | * show_boost = false and driver_data != BOOST freq | 223 | * show_boost = false and driver_data != BOOST freq |
230 | * display NON BOOST freqs | 224 | * display NON BOOST freqs |
231 | */ | 225 | */ |
232 | if (show_boost ^ (table[i].flags & CPUFREQ_BOOST_FREQ)) | 226 | if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ)) |
233 | continue; | 227 | continue; |
234 | 228 | ||
235 | count += sprintf(&buf[count], "%d ", table[i].frequency); | 229 | count += sprintf(&buf[count], "%d ", pos->frequency); |
236 | } | 230 | } |
237 | count += sprintf(&buf[count], "\n"); | 231 | count += sprintf(&buf[count], "\n"); |
238 | 232 | ||
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 5c4369b5d834..c913906a719e 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c | |||
@@ -530,6 +530,7 @@ static int longhaul_get_ranges(void) | |||
530 | 530 | ||
531 | static void longhaul_setup_voltagescaling(void) | 531 | static void longhaul_setup_voltagescaling(void) |
532 | { | 532 | { |
533 | struct cpufreq_frequency_table *freq_pos; | ||
533 | union msr_longhaul longhaul; | 534 | union msr_longhaul longhaul; |
534 | struct mV_pos minvid, maxvid, vid; | 535 | struct mV_pos minvid, maxvid, vid; |
535 | unsigned int j, speed, pos, kHz_step, numvscales; | 536 | unsigned int j, speed, pos, kHz_step, numvscales; |
@@ -608,18 +609,16 @@ static void longhaul_setup_voltagescaling(void) | |||
608 | /* Calculate kHz for one voltage step */ | 609 | /* Calculate kHz for one voltage step */ |
609 | kHz_step = (highest_speed - min_vid_speed) / numvscales; | 610 | kHz_step = (highest_speed - min_vid_speed) / numvscales; |
610 | 611 | ||
611 | j = 0; | 612 | cpufreq_for_each_entry(freq_pos, longhaul_table) { |
612 | while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { | 613 | speed = freq_pos->frequency; |
613 | speed = longhaul_table[j].frequency; | ||
614 | if (speed > min_vid_speed) | 614 | if (speed > min_vid_speed) |
615 | pos = (speed - min_vid_speed) / kHz_step + minvid.pos; | 615 | pos = (speed - min_vid_speed) / kHz_step + minvid.pos; |
616 | else | 616 | else |
617 | pos = minvid.pos; | 617 | pos = minvid.pos; |
618 | longhaul_table[j].driver_data |= mV_vrm_table[pos] << 8; | 618 | freq_pos->driver_data |= mV_vrm_table[pos] << 8; |
619 | vid = vrm_mV_table[mV_vrm_table[pos]]; | 619 | vid = vrm_mV_table[mV_vrm_table[pos]]; |
620 | printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", | 620 | printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", |
621 | speed, j, vid.mV); | 621 | speed, (int)(freq_pos - longhaul_table), vid.mV); |
622 | j++; | ||
623 | } | 622 | } |
624 | 623 | ||
625 | can_scale_voltage = 1; | 624 | can_scale_voltage = 1; |
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 84c84b5f0f3a..35dd4d7ffee0 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c | |||
@@ -136,9 +136,10 @@ void restore_astate(int cpu) | |||
136 | 136 | ||
137 | static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) | 137 | static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) |
138 | { | 138 | { |
139 | struct cpufreq_frequency_table *pos; | ||
139 | const u32 *max_freqp; | 140 | const u32 *max_freqp; |
140 | u32 max_freq; | 141 | u32 max_freq; |
141 | int i, cur_astate; | 142 | int cur_astate; |
142 | struct resource res; | 143 | struct resource res; |
143 | struct device_node *cpu, *dn; | 144 | struct device_node *cpu, *dn; |
144 | int err = -ENODEV; | 145 | int err = -ENODEV; |
@@ -197,10 +198,9 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
197 | pr_debug("initializing frequency table\n"); | 198 | pr_debug("initializing frequency table\n"); |
198 | 199 | ||
199 | /* initialize frequency table */ | 200 | /* initialize frequency table */ |
200 | for (i=0; pas_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { | 201 | cpufreq_for_each_entry(pos, pas_freqs) { |
201 | pas_freqs[i].frequency = | 202 | pos->frequency = get_astate_freq(pos->driver_data) * 100000; |
202 | get_astate_freq(pas_freqs[i].driver_data) * 100000; | 203 | pr_debug("%d: %d\n", (int)(pos - pas_freqs), pos->frequency); |
203 | pr_debug("%d: %d\n", i, pas_freqs[i].frequency); | ||
204 | } | 204 | } |
205 | 205 | ||
206 | cur_astate = get_cur_astate(policy->cpu); | 206 | cur_astate = get_cur_astate(policy->cpu); |
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index 78904e6ca4a0..c8012bc86910 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c | |||
@@ -151,6 +151,7 @@ static int powernow_k6_target(struct cpufreq_policy *policy, | |||
151 | 151 | ||
152 | static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | 152 | static int powernow_k6_cpu_init(struct cpufreq_policy *policy) |
153 | { | 153 | { |
154 | struct cpufreq_frequency_table *pos; | ||
154 | unsigned int i, f; | 155 | unsigned int i, f; |
155 | unsigned khz; | 156 | unsigned khz; |
156 | 157 | ||
@@ -168,12 +169,11 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | |||
168 | } | 169 | } |
169 | } | 170 | } |
170 | if (param_max_multiplier) { | 171 | if (param_max_multiplier) { |
171 | for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { | 172 | cpufreq_for_each_entry(pos, clock_ratio) |
172 | if (clock_ratio[i].driver_data == param_max_multiplier) { | 173 | if (pos->driver_data == param_max_multiplier) { |
173 | max_multiplier = param_max_multiplier; | 174 | max_multiplier = param_max_multiplier; |
174 | goto have_max_multiplier; | 175 | goto have_max_multiplier; |
175 | } | 176 | } |
176 | } | ||
177 | printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); | 177 | printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); |
178 | return -EINVAL; | 178 | return -EINVAL; |
179 | } | 179 | } |
@@ -201,12 +201,12 @@ have_busfreq: | |||
201 | param_busfreq = busfreq * 10; | 201 | param_busfreq = busfreq * 10; |
202 | 202 | ||
203 | /* table init */ | 203 | /* table init */ |
204 | for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { | 204 | cpufreq_for_each_entry(pos, clock_ratio) { |
205 | f = clock_ratio[i].driver_data; | 205 | f = pos->driver_data; |
206 | if (f > max_multiplier) | 206 | if (f > max_multiplier) |
207 | clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID; | 207 | pos->frequency = CPUFREQ_ENTRY_INVALID; |
208 | else | 208 | else |
209 | clock_ratio[i].frequency = busfreq * f; | 209 | pos->frequency = busfreq * f; |
210 | } | 210 | } |
211 | 211 | ||
212 | /* cpuinfo and default policy values */ | 212 | /* cpuinfo and default policy values */ |
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 5be8a48dba74..5a4c5a639f61 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c | |||
@@ -67,9 +67,10 @@ static int set_pmode(unsigned int cpu, unsigned int slow_mode) | |||
67 | 67 | ||
68 | static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) | 68 | static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) |
69 | { | 69 | { |
70 | struct cpufreq_frequency_table *pos; | ||
70 | const u32 *max_freqp; | 71 | const u32 *max_freqp; |
71 | u32 max_freq; | 72 | u32 max_freq; |
72 | int i, cur_pmode; | 73 | int cur_pmode; |
73 | struct device_node *cpu; | 74 | struct device_node *cpu; |
74 | 75 | ||
75 | cpu = of_get_cpu_node(policy->cpu, NULL); | 76 | cpu = of_get_cpu_node(policy->cpu, NULL); |
@@ -102,9 +103,9 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
102 | pr_debug("initializing frequency table\n"); | 103 | pr_debug("initializing frequency table\n"); |
103 | 104 | ||
104 | /* initialize frequency table */ | 105 | /* initialize frequency table */ |
105 | for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { | 106 | cpufreq_for_each_entry(pos, cbe_freqs) { |
106 | cbe_freqs[i].frequency = max_freq / cbe_freqs[i].driver_data; | 107 | pos->frequency = max_freq / pos->driver_data; |
107 | pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); | 108 | pr_debug("%d: %d\n", (int)(pos - cbe_freqs), pos->frequency); |
108 | } | 109 | } |
109 | 110 | ||
110 | /* if DEBUG is enabled set_pmode() measures the latency | 111 | /* if DEBUG is enabled set_pmode() measures the latency |
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 4626f90559b5..2fd53eaaec20 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c | |||
@@ -266,7 +266,7 @@ out: | |||
266 | static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) | 266 | static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) |
267 | { | 267 | { |
268 | int count, v, i, found; | 268 | int count, v, i, found; |
269 | struct cpufreq_frequency_table *freq; | 269 | struct cpufreq_frequency_table *pos; |
270 | struct s3c2416_dvfs *dvfs; | 270 | struct s3c2416_dvfs *dvfs; |
271 | 271 | ||
272 | count = regulator_count_voltages(s3c_freq->vddarm); | 272 | count = regulator_count_voltages(s3c_freq->vddarm); |
@@ -275,12 +275,11 @@ static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) | |||
275 | return; | 275 | return; |
276 | } | 276 | } |
277 | 277 | ||
278 | freq = s3c_freq->freq_table; | 278 | if (!count) |
279 | while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { | 279 | goto out; |
280 | if (freq->frequency == CPUFREQ_ENTRY_INVALID) | ||
281 | continue; | ||
282 | 280 | ||
283 | dvfs = &s3c2416_dvfs_table[freq->driver_data]; | 281 | cpufreq_for_each_valid_entry(pos, s3c_freq->freq_table) { |
282 | dvfs = &s3c2416_dvfs_table[pos->driver_data]; | ||
284 | found = 0; | 283 | found = 0; |
285 | 284 | ||
286 | /* Check only the min-voltage, more is always ok on S3C2416 */ | 285 | /* Check only the min-voltage, more is always ok on S3C2416 */ |
@@ -292,13 +291,12 @@ static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) | |||
292 | 291 | ||
293 | if (!found) { | 292 | if (!found) { |
294 | pr_debug("cpufreq: %dkHz unsupported by regulator\n", | 293 | pr_debug("cpufreq: %dkHz unsupported by regulator\n", |
295 | freq->frequency); | 294 | pos->frequency); |
296 | freq->frequency = CPUFREQ_ENTRY_INVALID; | 295 | pos->frequency = CPUFREQ_ENTRY_INVALID; |
297 | } | 296 | } |
298 | |||
299 | freq++; | ||
300 | } | 297 | } |
301 | 298 | ||
299 | out: | ||
302 | /* Guessed */ | 300 | /* Guessed */ |
303 | s3c_freq->regulator_latency = 1 * 1000 * 1000; | 301 | s3c_freq->regulator_latency = 1 * 1000 * 1000; |
304 | } | 302 | } |
@@ -338,7 +336,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = { | |||
338 | static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) | 336 | static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) |
339 | { | 337 | { |
340 | struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; | 338 | struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; |
341 | struct cpufreq_frequency_table *freq; | 339 | struct cpufreq_frequency_table *pos; |
342 | struct clk *msysclk; | 340 | struct clk *msysclk; |
343 | unsigned long rate; | 341 | unsigned long rate; |
344 | int ret; | 342 | int ret; |
@@ -427,31 +425,27 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) | |||
427 | s3c_freq->regulator_latency = 0; | 425 | s3c_freq->regulator_latency = 0; |
428 | #endif | 426 | #endif |
429 | 427 | ||
430 | freq = s3c_freq->freq_table; | 428 | cpufreq_for_each_entry(pos, s3c_freq->freq_table) { |
431 | while (freq->frequency != CPUFREQ_TABLE_END) { | ||
432 | /* special handling for dvs mode */ | 429 | /* special handling for dvs mode */ |
433 | if (freq->driver_data == 0) { | 430 | if (pos->driver_data == 0) { |
434 | if (!s3c_freq->hclk) { | 431 | if (!s3c_freq->hclk) { |
435 | pr_debug("cpufreq: %dkHz unsupported as it would need unavailable dvs mode\n", | 432 | pr_debug("cpufreq: %dkHz unsupported as it would need unavailable dvs mode\n", |
436 | freq->frequency); | 433 | pos->frequency); |
437 | freq->frequency = CPUFREQ_ENTRY_INVALID; | 434 | pos->frequency = CPUFREQ_ENTRY_INVALID; |
438 | } else { | 435 | } else { |
439 | freq++; | ||
440 | continue; | 436 | continue; |
441 | } | 437 | } |
442 | } | 438 | } |
443 | 439 | ||
444 | /* Check for frequencies we can generate */ | 440 | /* Check for frequencies we can generate */ |
445 | rate = clk_round_rate(s3c_freq->armdiv, | 441 | rate = clk_round_rate(s3c_freq->armdiv, |
446 | freq->frequency * 1000); | 442 | pos->frequency * 1000); |
447 | rate /= 1000; | 443 | rate /= 1000; |
448 | if (rate != freq->frequency) { | 444 | if (rate != pos->frequency) { |
449 | pr_debug("cpufreq: %dkHz unsupported by clock (clk_round_rate return %lu)\n", | 445 | pr_debug("cpufreq: %dkHz unsupported by clock (clk_round_rate return %lu)\n", |
450 | freq->frequency, rate); | 446 | pos->frequency, rate); |
451 | freq->frequency = CPUFREQ_ENTRY_INVALID; | 447 | pos->frequency = CPUFREQ_ENTRY_INVALID; |
452 | } | 448 | } |
453 | |||
454 | freq++; | ||
455 | } | 449 | } |
456 | 450 | ||
457 | /* Datasheet says PLL stabalisation time must be at least 300us, | 451 | /* Datasheet says PLL stabalisation time must be at least 300us, |
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index ff7d3ecb85f0..176e84cc3991 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c | |||
@@ -118,11 +118,10 @@ static void __init s3c64xx_cpufreq_config_regulator(void) | |||
118 | pr_err("Unable to check supported voltages\n"); | 118 | pr_err("Unable to check supported voltages\n"); |
119 | } | 119 | } |
120 | 120 | ||
121 | freq = s3c64xx_freq_table; | 121 | if (!count) |
122 | while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { | 122 | goto out; |
123 | if (freq->frequency == CPUFREQ_ENTRY_INVALID) | ||
124 | continue; | ||
125 | 123 | ||
124 | cpufreq_for_each_valid_entry(freq, s3c64xx_freq_table) { | ||
126 | dvfs = &s3c64xx_dvfs_table[freq->driver_data]; | 125 | dvfs = &s3c64xx_dvfs_table[freq->driver_data]; |
127 | found = 0; | 126 | found = 0; |
128 | 127 | ||
@@ -137,10 +136,9 @@ static void __init s3c64xx_cpufreq_config_regulator(void) | |||
137 | freq->frequency); | 136 | freq->frequency); |
138 | freq->frequency = CPUFREQ_ENTRY_INVALID; | 137 | freq->frequency = CPUFREQ_ENTRY_INVALID; |
139 | } | 138 | } |
140 | |||
141 | freq++; | ||
142 | } | 139 | } |
143 | 140 | ||
141 | out: | ||
144 | /* Guess based on having to do an I2C/SPI write; in future we | 142 | /* Guess based on having to do an I2C/SPI write; in future we |
145 | * will be able to query the regulator performance here. */ | 143 | * will be able to query the regulator performance here. */ |
146 | regulator_latency = 1 * 1000 * 1000; | 144 | regulator_latency = 1 * 1000 * 1000; |
@@ -179,8 +177,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) | |||
179 | } | 177 | } |
180 | #endif | 178 | #endif |
181 | 179 | ||
182 | freq = s3c64xx_freq_table; | 180 | cpufreq_for_each_entry(freq, s3c64xx_freq_table) { |
183 | while (freq->frequency != CPUFREQ_TABLE_END) { | ||
184 | unsigned long r; | 181 | unsigned long r; |
185 | 182 | ||
186 | /* Check for frequencies we can generate */ | 183 | /* Check for frequencies we can generate */ |
@@ -196,8 +193,6 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) | |||
196 | * frequency is the maximum we can support. */ | 193 | * frequency is the maximum we can support. */ |
197 | if (!vddarm && freq->frequency > clk_get_rate(policy->clk) / 1000) | 194 | if (!vddarm && freq->frequency > clk_get_rate(policy->clk) / 1000) |
198 | freq->frequency = CPUFREQ_ENTRY_INVALID; | 195 | freq->frequency = CPUFREQ_ENTRY_INVALID; |
199 | |||
200 | freq++; | ||
201 | } | 196 | } |
202 | 197 | ||
203 | /* Datasheet says PLL stabalisation time (if we were to use | 198 | /* Datasheet says PLL stabalisation time (if we were to use |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index be56e8ac95e6..aebde489c291 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -28,13 +28,13 @@ config EXTCON_ADC_JACK | |||
28 | Say Y here to enable extcon device driver based on ADC values. | 28 | Say Y here to enable extcon device driver based on ADC values. |
29 | 29 | ||
30 | config EXTCON_MAX14577 | 30 | config EXTCON_MAX14577 |
31 | tristate "MAX14577 EXTCON Support" | 31 | tristate "MAX14577/77836 EXTCON Support" |
32 | depends on MFD_MAX14577 | 32 | depends on MFD_MAX14577 |
33 | select IRQ_DOMAIN | 33 | select IRQ_DOMAIN |
34 | select REGMAP_I2C | 34 | select REGMAP_I2C |
35 | help | 35 | help |
36 | If you say yes here you get support for the MUIC device of | 36 | If you say yes here you get support for the MUIC device of |
37 | Maxim MAX14577 PMIC. The MAX14577 MUIC is a USB port accessory | 37 | Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory |
38 | detector and switch. | 38 | detector and switch. |
39 | 39 | ||
40 | config EXTCON_MAX77693 | 40 | config EXTCON_MAX77693 |
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index 3846941801b8..c76734a70171 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * extcon-max14577.c - MAX14577 extcon driver to support MAX14577 MUIC | 2 | * extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2013,2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -24,7 +25,6 @@ | |||
24 | #include <linux/mfd/max14577-private.h> | 25 | #include <linux/mfd/max14577-private.h> |
25 | #include <linux/extcon.h> | 26 | #include <linux/extcon.h> |
26 | 27 | ||
27 | #define DEV_NAME "max14577-muic" | ||
28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ | 28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ |
29 | 29 | ||
30 | enum max14577_muic_adc_debounce_time { | 30 | enum max14577_muic_adc_debounce_time { |
@@ -40,6 +40,42 @@ enum max14577_muic_status { | |||
40 | MAX14577_MUIC_STATUS_END, | 40 | MAX14577_MUIC_STATUS_END, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | /** | ||
44 | * struct max14577_muic_irq | ||
45 | * @irq: the index of irq list of MUIC device. | ||
46 | * @name: the name of irq. | ||
47 | * @virq: the virtual irq to use irq domain | ||
48 | */ | ||
49 | struct max14577_muic_irq { | ||
50 | unsigned int irq; | ||
51 | const char *name; | ||
52 | unsigned int virq; | ||
53 | }; | ||
54 | |||
55 | static struct max14577_muic_irq max14577_muic_irqs[] = { | ||
56 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
57 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
58 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
59 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
60 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
61 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
62 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
63 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
64 | }; | ||
65 | |||
66 | static struct max14577_muic_irq max77836_muic_irqs[] = { | ||
67 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
68 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
69 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
70 | { MAX77836_IRQ_INT1_ADC1K, "muic-ADC1K" }, | ||
71 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
72 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
73 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
74 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
75 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
76 | { MAX77836_IRQ_INT2_VIDRM, "muic-VIDRM" }, | ||
77 | }; | ||
78 | |||
43 | struct max14577_muic_info { | 79 | struct max14577_muic_info { |
44 | struct device *dev; | 80 | struct device *dev; |
45 | struct max14577 *max14577; | 81 | struct max14577 *max14577; |
@@ -48,6 +84,8 @@ struct max14577_muic_info { | |||
48 | int prev_chg_type; | 84 | int prev_chg_type; |
49 | u8 status[MAX14577_MUIC_STATUS_END]; | 85 | u8 status[MAX14577_MUIC_STATUS_END]; |
50 | 86 | ||
87 | struct max14577_muic_irq *muic_irqs; | ||
88 | unsigned int muic_irqs_num; | ||
51 | bool irq_adc; | 89 | bool irq_adc; |
52 | bool irq_chg; | 90 | bool irq_chg; |
53 | struct work_struct irq_work; | 91 | struct work_struct irq_work; |
@@ -74,29 +112,6 @@ enum max14577_muic_cable_group { | |||
74 | MAX14577_CABLE_GROUP_CHG, | 112 | MAX14577_CABLE_GROUP_CHG, |
75 | }; | 113 | }; |
76 | 114 | ||
77 | /** | ||
78 | * struct max14577_muic_irq | ||
79 | * @irq: the index of irq list of MUIC device. | ||
80 | * @name: the name of irq. | ||
81 | * @virq: the virtual irq to use irq domain | ||
82 | */ | ||
83 | struct max14577_muic_irq { | ||
84 | unsigned int irq; | ||
85 | const char *name; | ||
86 | unsigned int virq; | ||
87 | }; | ||
88 | |||
89 | static struct max14577_muic_irq muic_irqs[] = { | ||
90 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
91 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
92 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
93 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
94 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
95 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
96 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
97 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
98 | }; | ||
99 | |||
100 | /* Define supported accessory type */ | 115 | /* Define supported accessory type */ |
101 | enum max14577_muic_acc_type { | 116 | enum max14577_muic_acc_type { |
102 | MAX14577_MUIC_ADC_GROUND = 0x0, | 117 | MAX14577_MUIC_ADC_GROUND = 0x0, |
@@ -528,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work) | |||
528 | return; | 543 | return; |
529 | } | 544 | } |
530 | 545 | ||
531 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | 546 | /* |
547 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
548 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
549 | */ | ||
550 | static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
532 | { | 551 | { |
533 | struct max14577_muic_info *info = data; | ||
534 | int i, irq_type = -1; | ||
535 | |||
536 | /* | ||
537 | * We may be called multiple times for different nested IRQ-s. | ||
538 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
539 | * However we only need to know whether it was ADC, charger | ||
540 | * or both interrupts so decode IRQ and turn on proper flags. | ||
541 | */ | ||
542 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | ||
543 | if (irq == muic_irqs[i].virq) | ||
544 | irq_type = muic_irqs[i].irq; | ||
545 | |||
546 | switch (irq_type) { | 552 | switch (irq_type) { |
547 | case MAX14577_IRQ_INT1_ADC: | 553 | case MAX14577_IRQ_INT1_ADC: |
548 | case MAX14577_IRQ_INT1_ADCLOW: | 554 | case MAX14577_IRQ_INT1_ADCLOW: |
@@ -550,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
550 | /* Handle all of accessory except for | 556 | /* Handle all of accessory except for |
551 | type of charger accessory */ | 557 | type of charger accessory */ |
552 | info->irq_adc = true; | 558 | info->irq_adc = true; |
553 | break; | 559 | return 1; |
554 | case MAX14577_IRQ_INT2_CHGTYP: | 560 | case MAX14577_IRQ_INT2_CHGTYP: |
555 | case MAX14577_IRQ_INT2_CHGDETRUN: | 561 | case MAX14577_IRQ_INT2_CHGDETRUN: |
556 | case MAX14577_IRQ_INT2_DCDTMR: | 562 | case MAX14577_IRQ_INT2_DCDTMR: |
@@ -558,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
558 | case MAX14577_IRQ_INT2_VBVOLT: | 564 | case MAX14577_IRQ_INT2_VBVOLT: |
559 | /* Handle charger accessory */ | 565 | /* Handle charger accessory */ |
560 | info->irq_chg = true; | 566 | info->irq_chg = true; |
567 | return 1; | ||
568 | default: | ||
569 | return 0; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
575 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
576 | */ | ||
577 | static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
578 | { | ||
579 | /* First check common max14577 interrupts */ | ||
580 | if (max14577_parse_irq(info, irq_type)) | ||
581 | return 1; | ||
582 | |||
583 | switch (irq_type) { | ||
584 | case MAX77836_IRQ_INT1_ADC1K: | ||
585 | info->irq_adc = true; | ||
586 | return 1; | ||
587 | case MAX77836_IRQ_INT2_VIDRM: | ||
588 | /* Handle charger accessory */ | ||
589 | info->irq_chg = true; | ||
590 | return 1; | ||
591 | default: | ||
592 | return 0; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | ||
597 | { | ||
598 | struct max14577_muic_info *info = data; | ||
599 | int i, irq_type = -1; | ||
600 | bool irq_parsed; | ||
601 | |||
602 | /* | ||
603 | * We may be called multiple times for different nested IRQ-s. | ||
604 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
605 | * However we only need to know whether it was ADC, charger | ||
606 | * or both interrupts so decode IRQ and turn on proper flags. | ||
607 | */ | ||
608 | for (i = 0; i < info->muic_irqs_num; i++) | ||
609 | if (irq == info->muic_irqs[i].virq) | ||
610 | irq_type = info->muic_irqs[i].irq; | ||
611 | |||
612 | switch (info->max14577->dev_type) { | ||
613 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
614 | irq_parsed = max77836_parse_irq(info, irq_type); | ||
561 | break; | 615 | break; |
616 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
562 | default: | 617 | default: |
618 | irq_parsed = max14577_parse_irq(info, irq_type); | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | if (!irq_parsed) { | ||
563 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", | 623 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", |
564 | irq_type); | 624 | irq_type); |
565 | return IRQ_HANDLED; | 625 | return IRQ_HANDLED; |
@@ -644,9 +704,20 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
644 | 704 | ||
645 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); | 705 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); |
646 | 706 | ||
707 | switch (max14577->dev_type) { | ||
708 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
709 | info->muic_irqs = max77836_muic_irqs; | ||
710 | info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs); | ||
711 | break; | ||
712 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
713 | default: | ||
714 | info->muic_irqs = max14577_muic_irqs; | ||
715 | info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs); | ||
716 | } | ||
717 | |||
647 | /* Support irq domain for max14577 MUIC device */ | 718 | /* Support irq domain for max14577 MUIC device */ |
648 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { | 719 | for (i = 0; i < info->muic_irqs_num; i++) { |
649 | struct max14577_muic_irq *muic_irq = &muic_irqs[i]; | 720 | struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; |
650 | unsigned int virq = 0; | 721 | unsigned int virq = 0; |
651 | 722 | ||
652 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); | 723 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); |
@@ -673,7 +744,8 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
673 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | 744 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); |
674 | return -ENOMEM; | 745 | return -ENOMEM; |
675 | } | 746 | } |
676 | info->edev->name = DEV_NAME; | 747 | |
748 | info->edev->name = dev_name(&pdev->dev); | ||
677 | info->edev->supported_cable = max14577_extcon_cable; | 749 | info->edev->supported_cable = max14577_extcon_cable; |
678 | ret = extcon_dev_register(info->edev); | 750 | ret = extcon_dev_register(info->edev); |
679 | if (ret) { | 751 | if (ret) { |
@@ -735,18 +807,26 @@ static int max14577_muic_remove(struct platform_device *pdev) | |||
735 | return 0; | 807 | return 0; |
736 | } | 808 | } |
737 | 809 | ||
810 | static const struct platform_device_id max14577_muic_id[] = { | ||
811 | { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, }, | ||
812 | { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, }, | ||
813 | { } | ||
814 | }; | ||
815 | MODULE_DEVICE_TABLE(platform, max14577_muic_id); | ||
816 | |||
738 | static struct platform_driver max14577_muic_driver = { | 817 | static struct platform_driver max14577_muic_driver = { |
739 | .driver = { | 818 | .driver = { |
740 | .name = DEV_NAME, | 819 | .name = "max14577-muic", |
741 | .owner = THIS_MODULE, | 820 | .owner = THIS_MODULE, |
742 | }, | 821 | }, |
743 | .probe = max14577_muic_probe, | 822 | .probe = max14577_muic_probe, |
744 | .remove = max14577_muic_remove, | 823 | .remove = max14577_muic_remove, |
824 | .id_table = max14577_muic_id, | ||
745 | }; | 825 | }; |
746 | 826 | ||
747 | module_platform_driver(max14577_muic_driver); | 827 | module_platform_driver(max14577_muic_driver); |
748 | 828 | ||
749 | MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); | 829 | MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver"); |
750 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | 830 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
751 | MODULE_LICENSE("GPL"); | 831 | MODULE_LICENSE("GPL"); |
752 | MODULE_ALIAS("platform:extcon-max14577"); | 832 | MODULE_ALIAS("platform:extcon-max14577"); |
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 2776a09bee58..628b58494294 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
@@ -23,7 +23,8 @@ | |||
23 | enum { REG_RE, REG_FE, REG_IE }; | 23 | enum { REG_RE, REG_FE, REG_IE }; |
24 | 24 | ||
25 | #define CACHE_NR_REGS 3 | 25 | #define CACHE_NR_REGS 3 |
26 | #define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) | 26 | /* No variant has more than 24 GPIOs */ |
27 | #define CACHE_NR_BANKS (24 / 8) | ||
27 | 28 | ||
28 | struct stmpe_gpio { | 29 | struct stmpe_gpio { |
29 | struct gpio_chip chip; | 30 | struct gpio_chip chip; |
@@ -31,8 +32,6 @@ struct stmpe_gpio { | |||
31 | struct device *dev; | 32 | struct device *dev; |
32 | struct mutex irq_lock; | 33 | struct mutex irq_lock; |
33 | struct irq_domain *domain; | 34 | struct irq_domain *domain; |
34 | |||
35 | int irq_base; | ||
36 | unsigned norequest_mask; | 35 | unsigned norequest_mask; |
37 | 36 | ||
38 | /* Caches of interrupt control registers for bus_lock */ | 37 | /* Caches of interrupt control registers for bus_lock */ |
@@ -311,13 +310,8 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = { | |||
311 | static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio, | 310 | static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio, |
312 | struct device_node *np) | 311 | struct device_node *np) |
313 | { | 312 | { |
314 | int base = 0; | ||
315 | |||
316 | if (!np) | ||
317 | base = stmpe_gpio->irq_base; | ||
318 | |||
319 | stmpe_gpio->domain = irq_domain_add_simple(np, | 313 | stmpe_gpio->domain = irq_domain_add_simple(np, |
320 | stmpe_gpio->chip.ngpio, base, | 314 | stmpe_gpio->chip.ngpio, 0, |
321 | &stmpe_gpio_irq_simple_ops, stmpe_gpio); | 315 | &stmpe_gpio_irq_simple_ops, stmpe_gpio); |
322 | if (!stmpe_gpio->domain) { | 316 | if (!stmpe_gpio->domain) { |
323 | dev_err(stmpe_gpio->dev, "failed to create irqdomain\n"); | 317 | dev_err(stmpe_gpio->dev, "failed to create irqdomain\n"); |
@@ -354,7 +348,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
354 | #ifdef CONFIG_OF | 348 | #ifdef CONFIG_OF |
355 | stmpe_gpio->chip.of_node = np; | 349 | stmpe_gpio->chip.of_node = np; |
356 | #endif | 350 | #endif |
357 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | 351 | stmpe_gpio->chip.base = -1; |
358 | 352 | ||
359 | if (pdata) | 353 | if (pdata) |
360 | stmpe_gpio->norequest_mask = pdata->norequest_mask; | 354 | stmpe_gpio->norequest_mask = pdata->norequest_mask; |
@@ -362,9 +356,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
362 | of_property_read_u32(np, "st,norequest-mask", | 356 | of_property_read_u32(np, "st,norequest-mask", |
363 | &stmpe_gpio->norequest_mask); | 357 | &stmpe_gpio->norequest_mask); |
364 | 358 | ||
365 | if (irq >= 0) | 359 | if (irq < 0) |
366 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
367 | else | ||
368 | dev_info(&pdev->dev, | 360 | dev_info(&pdev->dev, |
369 | "device configured in no-irq mode; " | 361 | "device configured in no-irq mode; " |
370 | "irqs are not available\n"); | 362 | "irqs are not available\n"); |
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig index 1b37cf8cd204..7310e32b5991 100644 --- a/drivers/memstick/host/Kconfig +++ b/drivers/memstick/host/Kconfig | |||
@@ -52,3 +52,13 @@ config MEMSTICK_REALTEK_PCI | |||
52 | 52 | ||
53 | To compile this driver as a module, choose M here: the module will | 53 | To compile this driver as a module, choose M here: the module will |
54 | be called rtsx_pci_ms. | 54 | be called rtsx_pci_ms. |
55 | |||
56 | config MEMSTICK_REALTEK_USB | ||
57 | tristate "Realtek USB Memstick Card Interface Driver" | ||
58 | depends on MFD_RTSX_USB | ||
59 | help | ||
60 | Say Y here to include driver code to support Memstick card interface | ||
61 | of Realtek RTS5129/39 series USB card reader | ||
62 | |||
63 | To compile this driver as a module, choose M here: the module will | ||
64 | be called rts5139_ms. | ||
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile index af3459d7686e..491c9557441d 100644 --- a/drivers/memstick/host/Makefile +++ b/drivers/memstick/host/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o | |||
6 | obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o | 6 | obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o |
7 | obj-$(CONFIG_MEMSTICK_R592) += r592.o | 7 | obj-$(CONFIG_MEMSTICK_R592) += r592.o |
8 | obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o | 8 | obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o |
9 | obj-$(CONFIG_MEMSTICK_REALTEK_USB) += rtsx_usb_ms.o | ||
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c new file mode 100644 index 000000000000..a7282b7d4de8 --- /dev/null +++ b/drivers/memstick/host/rtsx_usb_ms.c | |||
@@ -0,0 +1,839 @@ | |||
1 | /* Realtek USB Memstick Card Interface driver | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * Author: | ||
18 | * Roger Tseng <rogerable@realtek.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/highmem.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | #include <linux/memstick.h> | ||
27 | #include <linux/kthread.h> | ||
28 | #include <linux/mfd/rtsx_usb.h> | ||
29 | #include <linux/pm_runtime.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/completion.h> | ||
33 | #include <asm/unaligned.h> | ||
34 | |||
35 | struct rtsx_usb_ms { | ||
36 | struct platform_device *pdev; | ||
37 | struct rtsx_ucr *ucr; | ||
38 | struct memstick_host *msh; | ||
39 | struct memstick_request *req; | ||
40 | |||
41 | struct mutex host_mutex; | ||
42 | struct work_struct handle_req; | ||
43 | |||
44 | struct task_struct *detect_ms; | ||
45 | struct completion detect_ms_exit; | ||
46 | |||
47 | u8 ssc_depth; | ||
48 | unsigned int clock; | ||
49 | int power_mode; | ||
50 | unsigned char ifmode; | ||
51 | bool eject; | ||
52 | }; | ||
53 | |||
54 | static inline struct device *ms_dev(struct rtsx_usb_ms *host) | ||
55 | { | ||
56 | return &(host->pdev->dev); | ||
57 | } | ||
58 | |||
59 | static inline void ms_clear_error(struct rtsx_usb_ms *host) | ||
60 | { | ||
61 | struct rtsx_ucr *ucr = host->ucr; | ||
62 | rtsx_usb_ep0_write_register(ucr, CARD_STOP, | ||
63 | MS_STOP | MS_CLR_ERR, | ||
64 | MS_STOP | MS_CLR_ERR); | ||
65 | |||
66 | rtsx_usb_clear_dma_err(ucr); | ||
67 | rtsx_usb_clear_fsm_err(ucr); | ||
68 | } | ||
69 | |||
70 | #ifdef DEBUG | ||
71 | |||
72 | static void ms_print_debug_regs(struct rtsx_usb_ms *host) | ||
73 | { | ||
74 | struct rtsx_ucr *ucr = host->ucr; | ||
75 | u16 i; | ||
76 | u8 *ptr; | ||
77 | |||
78 | /* Print MS host internal registers */ | ||
79 | rtsx_usb_init_cmd(ucr); | ||
80 | |||
81 | /* MS_CFG to MS_INT_REG */ | ||
82 | for (i = 0xFD40; i <= 0xFD44; i++) | ||
83 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0); | ||
84 | |||
85 | /* CARD_SHARE_MODE to CARD_GPIO */ | ||
86 | for (i = 0xFD51; i <= 0xFD56; i++) | ||
87 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0); | ||
88 | |||
89 | /* CARD_PULL_CTLx */ | ||
90 | for (i = 0xFD60; i <= 0xFD65; i++) | ||
91 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0); | ||
92 | |||
93 | /* CARD_DATA_SOURCE, CARD_SELECT, CARD_CLK_EN, CARD_PWR_CTL */ | ||
94 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_DATA_SOURCE, 0, 0); | ||
95 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_SELECT, 0, 0); | ||
96 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_CLK_EN, 0, 0); | ||
97 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_PWR_CTL, 0, 0); | ||
98 | |||
99 | rtsx_usb_send_cmd(ucr, MODE_CR, 100); | ||
100 | rtsx_usb_get_rsp(ucr, 21, 100); | ||
101 | |||
102 | ptr = ucr->rsp_buf; | ||
103 | for (i = 0xFD40; i <= 0xFD44; i++) | ||
104 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); | ||
105 | for (i = 0xFD51; i <= 0xFD56; i++) | ||
106 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); | ||
107 | for (i = 0xFD60; i <= 0xFD65; i++) | ||
108 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); | ||
109 | |||
110 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_DATA_SOURCE, *(ptr++)); | ||
111 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_SELECT, *(ptr++)); | ||
112 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_CLK_EN, *(ptr++)); | ||
113 | dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_PWR_CTL, *(ptr++)); | ||
114 | } | ||
115 | |||
116 | #else | ||
117 | |||
118 | static void ms_print_debug_regs(struct rtsx_usb_ms *host) | ||
119 | { | ||
120 | } | ||
121 | |||
122 | #endif | ||
123 | |||
124 | static int ms_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr) | ||
125 | { | ||
126 | rtsx_usb_init_cmd(ucr); | ||
127 | |||
128 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); | ||
129 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
130 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
131 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
132 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); | ||
133 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); | ||
134 | |||
135 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
136 | } | ||
137 | |||
138 | static int ms_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr) | ||
139 | { | ||
140 | rtsx_usb_init_cmd(ucr); | ||
141 | |||
142 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); | ||
143 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
144 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
145 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
146 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); | ||
147 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); | ||
148 | |||
149 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
150 | } | ||
151 | |||
152 | static int ms_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr) | ||
153 | { | ||
154 | rtsx_usb_init_cmd(ucr); | ||
155 | |||
156 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); | ||
157 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
158 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
159 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
160 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); | ||
161 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); | ||
162 | |||
163 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
164 | } | ||
165 | |||
166 | static int ms_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr) | ||
167 | { | ||
168 | rtsx_usb_init_cmd(ucr); | ||
169 | |||
170 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); | ||
171 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
172 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
173 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
174 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); | ||
175 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); | ||
176 | |||
177 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
178 | } | ||
179 | |||
180 | static int ms_power_on(struct rtsx_usb_ms *host) | ||
181 | { | ||
182 | struct rtsx_ucr *ucr = host->ucr; | ||
183 | int err; | ||
184 | |||
185 | dev_dbg(ms_dev(host), "%s\n", __func__); | ||
186 | |||
187 | rtsx_usb_init_cmd(ucr); | ||
188 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL); | ||
189 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE, | ||
190 | CARD_SHARE_MASK, CARD_SHARE_MS); | ||
191 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, | ||
192 | MS_CLK_EN, MS_CLK_EN); | ||
193 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
194 | if (err < 0) | ||
195 | return err; | ||
196 | |||
197 | if (CHECK_PKG(ucr, LQFP48)) | ||
198 | err = ms_pull_ctl_enable_lqfp48(ucr); | ||
199 | else | ||
200 | err = ms_pull_ctl_enable_qfn24(ucr); | ||
201 | if (err < 0) | ||
202 | return err; | ||
203 | |||
204 | err = rtsx_usb_write_register(ucr, CARD_PWR_CTL, | ||
205 | POWER_MASK, PARTIAL_POWER_ON); | ||
206 | if (err) | ||
207 | return err; | ||
208 | |||
209 | usleep_range(800, 1000); | ||
210 | |||
211 | rtsx_usb_init_cmd(ucr); | ||
212 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
213 | POWER_MASK, POWER_ON); | ||
214 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, | ||
215 | MS_OUTPUT_EN, MS_OUTPUT_EN); | ||
216 | |||
217 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
218 | } | ||
219 | |||
220 | static int ms_power_off(struct rtsx_usb_ms *host) | ||
221 | { | ||
222 | struct rtsx_ucr *ucr = host->ucr; | ||
223 | int err; | ||
224 | |||
225 | dev_dbg(ms_dev(host), "%s\n", __func__); | ||
226 | |||
227 | rtsx_usb_init_cmd(ucr); | ||
228 | |||
229 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0); | ||
230 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); | ||
231 | |||
232 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
233 | if (err < 0) | ||
234 | return err; | ||
235 | |||
236 | if (CHECK_PKG(ucr, LQFP48)) | ||
237 | return ms_pull_ctl_disable_lqfp48(ucr); | ||
238 | |||
239 | return ms_pull_ctl_disable_qfn24(ucr); | ||
240 | } | ||
241 | |||
242 | static int ms_transfer_data(struct rtsx_usb_ms *host, unsigned char data_dir, | ||
243 | u8 tpc, u8 cfg, struct scatterlist *sg) | ||
244 | { | ||
245 | struct rtsx_ucr *ucr = host->ucr; | ||
246 | int err; | ||
247 | unsigned int length = sg->length; | ||
248 | u16 sec_cnt = (u16)(length / 512); | ||
249 | u8 trans_mode, dma_dir, flag; | ||
250 | unsigned int pipe; | ||
251 | struct memstick_dev *card = host->msh->card; | ||
252 | |||
253 | dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n", | ||
254 | __func__, tpc, (data_dir == READ) ? "READ" : "WRITE", | ||
255 | length); | ||
256 | |||
257 | if (data_dir == READ) { | ||
258 | flag = MODE_CDIR; | ||
259 | dma_dir = DMA_DIR_FROM_CARD; | ||
260 | if (card->id.type != MEMSTICK_TYPE_PRO) | ||
261 | trans_mode = MS_TM_NORMAL_READ; | ||
262 | else | ||
263 | trans_mode = MS_TM_AUTO_READ; | ||
264 | pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN); | ||
265 | } else { | ||
266 | flag = MODE_CDOR; | ||
267 | dma_dir = DMA_DIR_TO_CARD; | ||
268 | if (card->id.type != MEMSTICK_TYPE_PRO) | ||
269 | trans_mode = MS_TM_NORMAL_WRITE; | ||
270 | else | ||
271 | trans_mode = MS_TM_AUTO_WRITE; | ||
272 | pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT); | ||
273 | } | ||
274 | |||
275 | rtsx_usb_init_cmd(ucr); | ||
276 | |||
277 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); | ||
278 | if (card->id.type == MEMSTICK_TYPE_PRO) { | ||
279 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_H, | ||
280 | 0xFF, (u8)(sec_cnt >> 8)); | ||
281 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_L, | ||
282 | 0xFF, (u8)sec_cnt); | ||
283 | } | ||
284 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); | ||
285 | |||
286 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3, | ||
287 | 0xFF, (u8)(length >> 24)); | ||
288 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2, | ||
289 | 0xFF, (u8)(length >> 16)); | ||
290 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1, | ||
291 | 0xFF, (u8)(length >> 8)); | ||
292 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, 0xFF, | ||
293 | (u8)length); | ||
294 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, | ||
295 | 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512); | ||
296 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, | ||
297 | 0x01, RING_BUFFER); | ||
298 | |||
299 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER, | ||
300 | 0xFF, MS_TRANSFER_START | trans_mode); | ||
301 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER, | ||
302 | MS_TRANSFER_END, MS_TRANSFER_END); | ||
303 | |||
304 | err = rtsx_usb_send_cmd(ucr, flag | STAGE_MS_STATUS, 100); | ||
305 | if (err) | ||
306 | return err; | ||
307 | |||
308 | err = rtsx_usb_transfer_data(ucr, pipe, sg, length, | ||
309 | 1, NULL, 10000); | ||
310 | if (err) | ||
311 | goto err_out; | ||
312 | |||
313 | err = rtsx_usb_get_rsp(ucr, 3, 15000); | ||
314 | if (err) | ||
315 | goto err_out; | ||
316 | |||
317 | if (ucr->rsp_buf[0] & MS_TRANSFER_ERR || | ||
318 | ucr->rsp_buf[1] & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { | ||
319 | err = -EIO; | ||
320 | goto err_out; | ||
321 | } | ||
322 | return 0; | ||
323 | err_out: | ||
324 | ms_clear_error(host); | ||
325 | return err; | ||
326 | } | ||
327 | |||
328 | static int ms_write_bytes(struct rtsx_usb_ms *host, u8 tpc, | ||
329 | u8 cfg, u8 cnt, u8 *data, u8 *int_reg) | ||
330 | { | ||
331 | struct rtsx_ucr *ucr = host->ucr; | ||
332 | int err, i; | ||
333 | |||
334 | dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc); | ||
335 | |||
336 | rtsx_usb_init_cmd(ucr); | ||
337 | |||
338 | for (i = 0; i < cnt; i++) | ||
339 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
340 | PPBUF_BASE2 + i, 0xFF, data[i]); | ||
341 | |||
342 | if (cnt % 2) | ||
343 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
344 | PPBUF_BASE2 + i, 0xFF, 0xFF); | ||
345 | |||
346 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); | ||
347 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); | ||
348 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); | ||
349 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, | ||
350 | 0x01, PINGPONG_BUFFER); | ||
351 | |||
352 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER, | ||
353 | 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); | ||
354 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER, | ||
355 | MS_TRANSFER_END, MS_TRANSFER_END); | ||
356 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0); | ||
357 | |||
358 | err = rtsx_usb_send_cmd(ucr, MODE_CR, 100); | ||
359 | if (err) | ||
360 | return err; | ||
361 | |||
362 | err = rtsx_usb_get_rsp(ucr, 2, 5000); | ||
363 | if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) { | ||
364 | u8 val; | ||
365 | |||
366 | rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val); | ||
367 | dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val); | ||
368 | |||
369 | if (int_reg) | ||
370 | *int_reg = val & 0x0F; | ||
371 | |||
372 | ms_print_debug_regs(host); | ||
373 | |||
374 | ms_clear_error(host); | ||
375 | |||
376 | if (!(tpc & 0x08)) { | ||
377 | if (val & MS_CRC16_ERR) | ||
378 | return -EIO; | ||
379 | } else { | ||
380 | if (!(val & 0x80)) { | ||
381 | if (val & (MS_INT_ERR | MS_INT_CMDNK)) | ||
382 | return -EIO; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | return -ETIMEDOUT; | ||
387 | } | ||
388 | |||
389 | if (int_reg) | ||
390 | *int_reg = ucr->rsp_buf[1] & 0x0F; | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int ms_read_bytes(struct rtsx_usb_ms *host, u8 tpc, | ||
396 | u8 cfg, u8 cnt, u8 *data, u8 *int_reg) | ||
397 | { | ||
398 | struct rtsx_ucr *ucr = host->ucr; | ||
399 | int err, i; | ||
400 | u8 *ptr; | ||
401 | |||
402 | dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc); | ||
403 | |||
404 | rtsx_usb_init_cmd(ucr); | ||
405 | |||
406 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); | ||
407 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); | ||
408 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); | ||
409 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, | ||
410 | 0x01, PINGPONG_BUFFER); | ||
411 | |||
412 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER, | ||
413 | 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES); | ||
414 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER, | ||
415 | MS_TRANSFER_END, MS_TRANSFER_END); | ||
416 | for (i = 0; i < cnt - 1; i++) | ||
417 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); | ||
418 | if (cnt % 2) | ||
419 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0); | ||
420 | else | ||
421 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, | ||
422 | PPBUF_BASE2 + cnt - 1, 0, 0); | ||
423 | |||
424 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0); | ||
425 | |||
426 | err = rtsx_usb_send_cmd(ucr, MODE_CR, 100); | ||
427 | if (err) | ||
428 | return err; | ||
429 | |||
430 | err = rtsx_usb_get_rsp(ucr, cnt + 2, 5000); | ||
431 | if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) { | ||
432 | u8 val; | ||
433 | |||
434 | rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val); | ||
435 | dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val); | ||
436 | |||
437 | if (int_reg && (host->ifmode != MEMSTICK_SERIAL)) | ||
438 | *int_reg = val & 0x0F; | ||
439 | |||
440 | ms_print_debug_regs(host); | ||
441 | |||
442 | ms_clear_error(host); | ||
443 | |||
444 | if (!(tpc & 0x08)) { | ||
445 | if (val & MS_CRC16_ERR) | ||
446 | return -EIO; | ||
447 | } else { | ||
448 | if (!(val & 0x80)) { | ||
449 | if (val & (MS_INT_ERR | MS_INT_CMDNK)) | ||
450 | return -EIO; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | return -ETIMEDOUT; | ||
455 | } | ||
456 | |||
457 | ptr = ucr->rsp_buf + 1; | ||
458 | for (i = 0; i < cnt; i++) | ||
459 | data[i] = *ptr++; | ||
460 | |||
461 | |||
462 | if (int_reg && (host->ifmode != MEMSTICK_SERIAL)) | ||
463 | *int_reg = *ptr & 0x0F; | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int rtsx_usb_ms_issue_cmd(struct rtsx_usb_ms *host) | ||
469 | { | ||
470 | struct memstick_request *req = host->req; | ||
471 | int err = 0; | ||
472 | u8 cfg = 0, int_reg; | ||
473 | |||
474 | dev_dbg(ms_dev(host), "%s\n", __func__); | ||
475 | |||
476 | if (req->need_card_int) { | ||
477 | if (host->ifmode != MEMSTICK_SERIAL) | ||
478 | cfg = WAIT_INT; | ||
479 | } | ||
480 | |||
481 | if (req->long_data) { | ||
482 | err = ms_transfer_data(host, req->data_dir, | ||
483 | req->tpc, cfg, &(req->sg)); | ||
484 | } else { | ||
485 | if (req->data_dir == READ) | ||
486 | err = ms_read_bytes(host, req->tpc, cfg, | ||
487 | req->data_len, req->data, &int_reg); | ||
488 | else | ||
489 | err = ms_write_bytes(host, req->tpc, cfg, | ||
490 | req->data_len, req->data, &int_reg); | ||
491 | } | ||
492 | if (err < 0) | ||
493 | return err; | ||
494 | |||
495 | if (req->need_card_int) { | ||
496 | if (host->ifmode == MEMSTICK_SERIAL) { | ||
497 | err = ms_read_bytes(host, MS_TPC_GET_INT, | ||
498 | NO_WAIT_INT, 1, &req->int_reg, NULL); | ||
499 | if (err < 0) | ||
500 | return err; | ||
501 | } else { | ||
502 | |||
503 | if (int_reg & MS_INT_CMDNK) | ||
504 | req->int_reg |= MEMSTICK_INT_CMDNAK; | ||
505 | if (int_reg & MS_INT_BREQ) | ||
506 | req->int_reg |= MEMSTICK_INT_BREQ; | ||
507 | if (int_reg & MS_INT_ERR) | ||
508 | req->int_reg |= MEMSTICK_INT_ERR; | ||
509 | if (int_reg & MS_INT_CED) | ||
510 | req->int_reg |= MEMSTICK_INT_CED; | ||
511 | } | ||
512 | dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", req->int_reg); | ||
513 | } | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static void rtsx_usb_ms_handle_req(struct work_struct *work) | ||
519 | { | ||
520 | struct rtsx_usb_ms *host = container_of(work, | ||
521 | struct rtsx_usb_ms, handle_req); | ||
522 | struct rtsx_ucr *ucr = host->ucr; | ||
523 | struct memstick_host *msh = host->msh; | ||
524 | int rc; | ||
525 | |||
526 | if (!host->req) { | ||
527 | do { | ||
528 | rc = memstick_next_req(msh, &host->req); | ||
529 | dev_dbg(ms_dev(host), "next req %d\n", rc); | ||
530 | |||
531 | if (!rc) { | ||
532 | mutex_lock(&ucr->dev_mutex); | ||
533 | |||
534 | if (rtsx_usb_card_exclusive_check(ucr, | ||
535 | RTSX_USB_MS_CARD)) | ||
536 | host->req->error = -EIO; | ||
537 | else | ||
538 | host->req->error = | ||
539 | rtsx_usb_ms_issue_cmd(host); | ||
540 | |||
541 | mutex_unlock(&ucr->dev_mutex); | ||
542 | |||
543 | dev_dbg(ms_dev(host), "req result %d\n", | ||
544 | host->req->error); | ||
545 | } | ||
546 | } while (!rc); | ||
547 | } | ||
548 | |||
549 | } | ||
550 | |||
551 | static void rtsx_usb_ms_request(struct memstick_host *msh) | ||
552 | { | ||
553 | struct rtsx_usb_ms *host = memstick_priv(msh); | ||
554 | |||
555 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | ||
556 | |||
557 | if (!host->eject) | ||
558 | schedule_work(&host->handle_req); | ||
559 | } | ||
560 | |||
561 | static int rtsx_usb_ms_set_param(struct memstick_host *msh, | ||
562 | enum memstick_param param, int value) | ||
563 | { | ||
564 | struct rtsx_usb_ms *host = memstick_priv(msh); | ||
565 | struct rtsx_ucr *ucr = host->ucr; | ||
566 | unsigned int clock = 0; | ||
567 | u8 ssc_depth = 0; | ||
568 | int err; | ||
569 | |||
570 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", | ||
571 | __func__, param, value); | ||
572 | |||
573 | mutex_lock(&ucr->dev_mutex); | ||
574 | |||
575 | err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD); | ||
576 | if (err) | ||
577 | goto out; | ||
578 | |||
579 | switch (param) { | ||
580 | case MEMSTICK_POWER: | ||
581 | if (value == host->power_mode) | ||
582 | break; | ||
583 | |||
584 | if (value == MEMSTICK_POWER_ON) { | ||
585 | pm_runtime_get_sync(ms_dev(host)); | ||
586 | err = ms_power_on(host); | ||
587 | } else if (value == MEMSTICK_POWER_OFF) { | ||
588 | err = ms_power_off(host); | ||
589 | if (host->msh->card) | ||
590 | pm_runtime_put_noidle(ms_dev(host)); | ||
591 | else | ||
592 | pm_runtime_put(ms_dev(host)); | ||
593 | } else | ||
594 | err = -EINVAL; | ||
595 | if (!err) | ||
596 | host->power_mode = value; | ||
597 | break; | ||
598 | |||
599 | case MEMSTICK_INTERFACE: | ||
600 | if (value == MEMSTICK_SERIAL) { | ||
601 | clock = 19000000; | ||
602 | ssc_depth = SSC_DEPTH_512K; | ||
603 | err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A, | ||
604 | MS_BUS_WIDTH_1 | PUSH_TIME_DEFAULT); | ||
605 | if (err < 0) | ||
606 | break; | ||
607 | } else if (value == MEMSTICK_PAR4) { | ||
608 | clock = 39000000; | ||
609 | ssc_depth = SSC_DEPTH_1M; | ||
610 | |||
611 | err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A, | ||
612 | MS_BUS_WIDTH_4 | PUSH_TIME_ODD | | ||
613 | MS_NO_CHECK_INT); | ||
614 | if (err < 0) | ||
615 | break; | ||
616 | } else { | ||
617 | err = -EINVAL; | ||
618 | break; | ||
619 | } | ||
620 | |||
621 | err = rtsx_usb_switch_clock(ucr, clock, | ||
622 | ssc_depth, false, true, false); | ||
623 | if (err < 0) { | ||
624 | dev_dbg(ms_dev(host), "switch clock failed\n"); | ||
625 | break; | ||
626 | } | ||
627 | |||
628 | host->ssc_depth = ssc_depth; | ||
629 | host->clock = clock; | ||
630 | host->ifmode = value; | ||
631 | break; | ||
632 | default: | ||
633 | err = -EINVAL; | ||
634 | break; | ||
635 | } | ||
636 | out: | ||
637 | mutex_unlock(&ucr->dev_mutex); | ||
638 | |||
639 | /* power-on delay */ | ||
640 | if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) | ||
641 | usleep_range(10000, 12000); | ||
642 | |||
643 | dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err); | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | #ifdef CONFIG_PM_SLEEP | ||
648 | static int rtsx_usb_ms_suspend(struct device *dev) | ||
649 | { | ||
650 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); | ||
651 | struct memstick_host *msh = host->msh; | ||
652 | |||
653 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | ||
654 | |||
655 | memstick_suspend_host(msh); | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int rtsx_usb_ms_resume(struct device *dev) | ||
660 | { | ||
661 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); | ||
662 | struct memstick_host *msh = host->msh; | ||
663 | |||
664 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | ||
665 | |||
666 | memstick_resume_host(msh); | ||
667 | return 0; | ||
668 | } | ||
669 | #endif /* CONFIG_PM_SLEEP */ | ||
670 | |||
671 | /* | ||
672 | * Thread function of ms card slot detection. The thread starts right after | ||
673 | * successful host addition. It stops while the driver removal function sets | ||
674 | * host->eject true. | ||
675 | */ | ||
676 | static int rtsx_usb_detect_ms_card(void *__host) | ||
677 | { | ||
678 | struct rtsx_usb_ms *host = (struct rtsx_usb_ms *)__host; | ||
679 | struct rtsx_ucr *ucr = host->ucr; | ||
680 | u8 val = 0; | ||
681 | int err; | ||
682 | |||
683 | for (;;) { | ||
684 | mutex_lock(&ucr->dev_mutex); | ||
685 | |||
686 | /* Check pending MS card changes */ | ||
687 | err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val); | ||
688 | if (err) { | ||
689 | mutex_unlock(&ucr->dev_mutex); | ||
690 | goto poll_again; | ||
691 | } | ||
692 | |||
693 | /* Clear the pending */ | ||
694 | rtsx_usb_write_register(ucr, CARD_INT_PEND, | ||
695 | XD_INT | MS_INT | SD_INT, | ||
696 | XD_INT | MS_INT | SD_INT); | ||
697 | |||
698 | mutex_unlock(&ucr->dev_mutex); | ||
699 | |||
700 | if (val & MS_INT) { | ||
701 | dev_dbg(ms_dev(host), "MS slot change detected\n"); | ||
702 | memstick_detect_change(host->msh); | ||
703 | } | ||
704 | |||
705 | poll_again: | ||
706 | if (host->eject) | ||
707 | break; | ||
708 | |||
709 | msleep(1000); | ||
710 | } | ||
711 | |||
712 | complete(&host->detect_ms_exit); | ||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) | ||
717 | { | ||
718 | struct memstick_host *msh; | ||
719 | struct rtsx_usb_ms *host; | ||
720 | struct rtsx_ucr *ucr; | ||
721 | int err; | ||
722 | |||
723 | ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); | ||
724 | if (!ucr) | ||
725 | return -ENXIO; | ||
726 | |||
727 | dev_dbg(&(pdev->dev), | ||
728 | "Realtek USB Memstick controller found\n"); | ||
729 | |||
730 | msh = memstick_alloc_host(sizeof(*host), &pdev->dev); | ||
731 | if (!msh) | ||
732 | return -ENOMEM; | ||
733 | |||
734 | host = memstick_priv(msh); | ||
735 | host->ucr = ucr; | ||
736 | host->msh = msh; | ||
737 | host->pdev = pdev; | ||
738 | host->power_mode = MEMSTICK_POWER_OFF; | ||
739 | platform_set_drvdata(pdev, host); | ||
740 | |||
741 | mutex_init(&host->host_mutex); | ||
742 | INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req); | ||
743 | |||
744 | init_completion(&host->detect_ms_exit); | ||
745 | host->detect_ms = kthread_create(rtsx_usb_detect_ms_card, host, | ||
746 | "rtsx_usb_ms_%d", pdev->id); | ||
747 | if (IS_ERR(host->detect_ms)) { | ||
748 | dev_dbg(&(pdev->dev), | ||
749 | "Unable to create polling thread.\n"); | ||
750 | err = PTR_ERR(host->detect_ms); | ||
751 | goto err_out; | ||
752 | } | ||
753 | |||
754 | msh->request = rtsx_usb_ms_request; | ||
755 | msh->set_param = rtsx_usb_ms_set_param; | ||
756 | msh->caps = MEMSTICK_CAP_PAR4; | ||
757 | |||
758 | pm_runtime_enable(&pdev->dev); | ||
759 | err = memstick_add_host(msh); | ||
760 | if (err) | ||
761 | goto err_out; | ||
762 | |||
763 | wake_up_process(host->detect_ms); | ||
764 | return 0; | ||
765 | err_out: | ||
766 | memstick_free_host(msh); | ||
767 | return err; | ||
768 | } | ||
769 | |||
770 | static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) | ||
771 | { | ||
772 | struct rtsx_usb_ms *host = platform_get_drvdata(pdev); | ||
773 | struct memstick_host *msh; | ||
774 | int err; | ||
775 | |||
776 | msh = host->msh; | ||
777 | host->eject = true; | ||
778 | cancel_work_sync(&host->handle_req); | ||
779 | |||
780 | mutex_lock(&host->host_mutex); | ||
781 | if (host->req) { | ||
782 | dev_dbg(&(pdev->dev), | ||
783 | "%s: Controller removed during transfer\n", | ||
784 | dev_name(&msh->dev)); | ||
785 | host->req->error = -ENOMEDIUM; | ||
786 | do { | ||
787 | err = memstick_next_req(msh, &host->req); | ||
788 | if (!err) | ||
789 | host->req->error = -ENOMEDIUM; | ||
790 | } while (!err); | ||
791 | } | ||
792 | mutex_unlock(&host->host_mutex); | ||
793 | |||
794 | wait_for_completion(&host->detect_ms_exit); | ||
795 | memstick_remove_host(msh); | ||
796 | memstick_free_host(msh); | ||
797 | |||
798 | /* Balance possible unbalanced usage count | ||
799 | * e.g. unconditional module removal | ||
800 | */ | ||
801 | if (pm_runtime_active(ms_dev(host))) | ||
802 | pm_runtime_put(ms_dev(host)); | ||
803 | |||
804 | pm_runtime_disable(&pdev->dev); | ||
805 | platform_set_drvdata(pdev, NULL); | ||
806 | |||
807 | dev_dbg(&(pdev->dev), | ||
808 | ": Realtek USB Memstick controller has been removed\n"); | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static SIMPLE_DEV_PM_OPS(rtsx_usb_ms_pm_ops, | ||
814 | rtsx_usb_ms_suspend, rtsx_usb_ms_resume); | ||
815 | |||
816 | static struct platform_device_id rtsx_usb_ms_ids[] = { | ||
817 | { | ||
818 | .name = "rtsx_usb_ms", | ||
819 | }, { | ||
820 | /* sentinel */ | ||
821 | } | ||
822 | }; | ||
823 | MODULE_DEVICE_TABLE(platform, rtsx_usb_ms_ids); | ||
824 | |||
825 | static struct platform_driver rtsx_usb_ms_driver = { | ||
826 | .probe = rtsx_usb_ms_drv_probe, | ||
827 | .remove = rtsx_usb_ms_drv_remove, | ||
828 | .id_table = rtsx_usb_ms_ids, | ||
829 | .driver = { | ||
830 | .owner = THIS_MODULE, | ||
831 | .name = "rtsx_usb_ms", | ||
832 | .pm = &rtsx_usb_ms_pm_ops, | ||
833 | }, | ||
834 | }; | ||
835 | module_platform_driver(rtsx_usb_ms_driver); | ||
836 | |||
837 | MODULE_LICENSE("GPL v2"); | ||
838 | MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>"); | ||
839 | MODULE_DESCRIPTION("Realtek USB Memstick Card Host Driver"); | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 33834120d057..e166d7176d7a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -331,15 +331,15 @@ config MFD_88PM860X | |||
331 | battery-charger under the corresponding menus. | 331 | battery-charger under the corresponding menus. |
332 | 332 | ||
333 | config MFD_MAX14577 | 333 | config MFD_MAX14577 |
334 | bool "Maxim Semiconductor MAX14577 MUIC + Charger Support" | 334 | bool "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support" |
335 | depends on I2C=y | 335 | depends on I2C=y |
336 | select MFD_CORE | 336 | select MFD_CORE |
337 | select REGMAP_I2C | 337 | select REGMAP_I2C |
338 | select REGMAP_IRQ | 338 | select REGMAP_IRQ |
339 | select IRQ_DOMAIN | 339 | select IRQ_DOMAIN |
340 | help | 340 | help |
341 | Say yes here to add support for Maxim Semiconductor MAX14577. | 341 | Say yes here to add support for Maxim Semiconductor MAX14577 and |
342 | This is a Micro-USB IC with Charger controls on chip. | 342 | MAX77836 Micro-USB ICs with battery charger. |
343 | This driver provides common support for accessing the device; | 343 | This driver provides common support for accessing the device; |
344 | additional drivers must be enabled in order to use the functionality | 344 | additional drivers must be enabled in order to use the functionality |
345 | of the device. | 345 | of the device. |
@@ -675,6 +675,7 @@ config MFD_DB8500_PRCMU | |||
675 | config MFD_STMPE | 675 | config MFD_STMPE |
676 | bool "STMicroelectronics STMPE" | 676 | bool "STMicroelectronics STMPE" |
677 | depends on (I2C=y || SPI_MASTER=y) | 677 | depends on (I2C=y || SPI_MASTER=y) |
678 | depends on OF | ||
678 | select MFD_CORE | 679 | select MFD_CORE |
679 | help | 680 | help |
680 | Support for the STMPE family of I/O Expanders from | 681 | Support for the STMPE family of I/O Expanders from |
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 1c3ae57082ed..07e6e27be23c 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
@@ -508,19 +508,31 @@ int arizona_of_get_type(struct device *dev) | |||
508 | } | 508 | } |
509 | EXPORT_SYMBOL_GPL(arizona_of_get_type); | 509 | EXPORT_SYMBOL_GPL(arizona_of_get_type); |
510 | 510 | ||
511 | int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
512 | bool mandatory) | ||
513 | { | ||
514 | int gpio; | ||
515 | |||
516 | gpio = of_get_named_gpio(arizona->dev->of_node, prop, 0); | ||
517 | if (gpio < 0) { | ||
518 | if (mandatory) | ||
519 | dev_err(arizona->dev, | ||
520 | "Mandatory DT gpio %s missing/malformed: %d\n", | ||
521 | prop, gpio); | ||
522 | |||
523 | gpio = 0; | ||
524 | } | ||
525 | |||
526 | return gpio; | ||
527 | } | ||
528 | EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio); | ||
529 | |||
511 | static int arizona_of_get_core_pdata(struct arizona *arizona) | 530 | static int arizona_of_get_core_pdata(struct arizona *arizona) |
512 | { | 531 | { |
532 | struct arizona_pdata *pdata = &arizona->pdata; | ||
513 | int ret, i; | 533 | int ret, i; |
514 | 534 | ||
515 | arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, | 535 | pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true); |
516 | "wlf,reset", 0); | ||
517 | if (arizona->pdata.reset < 0) | ||
518 | arizona->pdata.reset = 0; | ||
519 | |||
520 | arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node, | ||
521 | "wlf,ldoena", 0); | ||
522 | if (arizona->pdata.ldoena < 0) | ||
523 | arizona->pdata.ldoena = 0; | ||
524 | 536 | ||
525 | ret = of_property_read_u32_array(arizona->dev->of_node, | 537 | ret = of_property_read_u32_array(arizona->dev->of_node, |
526 | "wlf,gpio-defaults", | 538 | "wlf,gpio-defaults", |
@@ -652,6 +664,9 @@ int arizona_dev_init(struct arizona *arizona) | |||
652 | return -EINVAL; | 664 | return -EINVAL; |
653 | } | 665 | } |
654 | 666 | ||
667 | /* Mark DCVDD as external, LDO1 driver will clear if internal */ | ||
668 | arizona->external_dcvdd = true; | ||
669 | |||
655 | ret = mfd_add_devices(arizona->dev, -1, early_devs, | 670 | ret = mfd_add_devices(arizona->dev, -1, early_devs, |
656 | ARRAY_SIZE(early_devs), NULL, 0, NULL); | 671 | ARRAY_SIZE(early_devs), NULL, 0, NULL); |
657 | if (ret != 0) { | 672 | if (ret != 0) { |
@@ -851,14 +866,6 @@ int arizona_dev_init(struct arizona *arizona) | |||
851 | arizona->pdata.gpio_defaults[i]); | 866 | arizona->pdata.gpio_defaults[i]); |
852 | } | 867 | } |
853 | 868 | ||
854 | /* | ||
855 | * LDO1 can only be used to supply DCVDD so if it has no | ||
856 | * consumers then DCVDD is supplied externally. | ||
857 | */ | ||
858 | if (arizona->pdata.ldo1 && | ||
859 | arizona->pdata.ldo1->num_consumer_supplies == 0) | ||
860 | arizona->external_dcvdd = true; | ||
861 | |||
862 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); | 869 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); |
863 | pm_runtime_use_autosuspend(arizona->dev); | 870 | pm_runtime_use_autosuspend(arizona->dev); |
864 | pm_runtime_enable(arizona->dev); | 871 | pm_runtime_enable(arizona->dev); |
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7694e0700d34..b11fdd63eecd 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -1734,18 +1734,17 @@ static struct cpufreq_frequency_table db8500_cpufreq_table[] = { | |||
1734 | 1734 | ||
1735 | static long round_armss_rate(unsigned long rate) | 1735 | static long round_armss_rate(unsigned long rate) |
1736 | { | 1736 | { |
1737 | struct cpufreq_frequency_table *pos; | ||
1737 | long freq = 0; | 1738 | long freq = 0; |
1738 | int i = 0; | ||
1739 | 1739 | ||
1740 | /* cpufreq table frequencies is in KHz. */ | 1740 | /* cpufreq table frequencies is in KHz. */ |
1741 | rate = rate / 1000; | 1741 | rate = rate / 1000; |
1742 | 1742 | ||
1743 | /* Find the corresponding arm opp from the cpufreq table. */ | 1743 | /* Find the corresponding arm opp from the cpufreq table. */ |
1744 | while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) { | 1744 | cpufreq_for_each_entry(pos, db8500_cpufreq_table) { |
1745 | freq = db8500_cpufreq_table[i].frequency; | 1745 | freq = pos->frequency; |
1746 | if (freq == rate) | 1746 | if (freq == rate) |
1747 | break; | 1747 | break; |
1748 | i++; | ||
1749 | } | 1748 | } |
1750 | 1749 | ||
1751 | /* Return the last valid value, even if a match was not found. */ | 1750 | /* Return the last valid value, even if a match was not found. */ |
@@ -1886,23 +1885,21 @@ static void set_clock_rate(u8 clock, unsigned long rate) | |||
1886 | 1885 | ||
1887 | static int set_armss_rate(unsigned long rate) | 1886 | static int set_armss_rate(unsigned long rate) |
1888 | { | 1887 | { |
1889 | int i = 0; | 1888 | struct cpufreq_frequency_table *pos; |
1890 | 1889 | ||
1891 | /* cpufreq table frequencies is in KHz. */ | 1890 | /* cpufreq table frequencies is in KHz. */ |
1892 | rate = rate / 1000; | 1891 | rate = rate / 1000; |
1893 | 1892 | ||
1894 | /* Find the corresponding arm opp from the cpufreq table. */ | 1893 | /* Find the corresponding arm opp from the cpufreq table. */ |
1895 | while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) { | 1894 | cpufreq_for_each_entry(pos, db8500_cpufreq_table) |
1896 | if (db8500_cpufreq_table[i].frequency == rate) | 1895 | if (pos->frequency == rate) |
1897 | break; | 1896 | break; |
1898 | i++; | ||
1899 | } | ||
1900 | 1897 | ||
1901 | if (db8500_cpufreq_table[i].frequency != rate) | 1898 | if (pos->frequency != rate) |
1902 | return -EINVAL; | 1899 | return -EINVAL; |
1903 | 1900 | ||
1904 | /* Set the new arm opp. */ | 1901 | /* Set the new arm opp. */ |
1905 | return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].driver_data); | 1902 | return db8500_prcmu_set_arm_opp(pos->driver_data); |
1906 | } | 1903 | } |
1907 | 1904 | ||
1908 | static int set_plldsi_rate(unsigned long rate) | 1905 | static int set_plldsi_rate(unsigned long rate) |
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 5f13cefe8def..484d372a4892 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * max14577.c - mfd core driver for the Maxim 14577 | 2 | * max14577.c - mfd core driver for the Maxim 14577/77836 |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> |
7 | * | 7 | * |
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/of_device.h> | ||
24 | #include <linux/mfd/core.h> | 25 | #include <linux/mfd/core.h> |
25 | #include <linux/mfd/max14577.h> | 26 | #include <linux/mfd/max14577.h> |
26 | #include <linux/mfd/max14577-private.h> | 27 | #include <linux/mfd/max14577-private.h> |
@@ -37,7 +38,38 @@ static struct mfd_cell max14577_devs[] = { | |||
37 | { .name = "max14577-charger", }, | 38 | { .name = "max14577-charger", }, |
38 | }; | 39 | }; |
39 | 40 | ||
40 | static bool max14577_volatile_reg(struct device *dev, unsigned int reg) | 41 | static struct mfd_cell max77836_devs[] = { |
42 | { | ||
43 | .name = "max77836-muic", | ||
44 | .of_compatible = "maxim,max77836-muic", | ||
45 | }, | ||
46 | { | ||
47 | .name = "max77836-regulator", | ||
48 | .of_compatible = "maxim,max77836-regulator", | ||
49 | }, | ||
50 | { | ||
51 | .name = "max77836-charger", | ||
52 | .of_compatible = "maxim,max77836-charger", | ||
53 | }, | ||
54 | { | ||
55 | .name = "max77836-battery", | ||
56 | .of_compatible = "maxim,max77836-battery", | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static struct of_device_id max14577_dt_match[] = { | ||
61 | { | ||
62 | .compatible = "maxim,max14577", | ||
63 | .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, | ||
64 | }, | ||
65 | { | ||
66 | .compatible = "maxim,max77836", | ||
67 | .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, | ||
68 | }, | ||
69 | {}, | ||
70 | }; | ||
71 | |||
72 | static bool max14577_muic_volatile_reg(struct device *dev, unsigned int reg) | ||
41 | { | 73 | { |
42 | switch (reg) { | 74 | switch (reg) { |
43 | case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3: | 75 | case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3: |
@@ -48,49 +80,221 @@ static bool max14577_volatile_reg(struct device *dev, unsigned int reg) | |||
48 | return false; | 80 | return false; |
49 | } | 81 | } |
50 | 82 | ||
51 | static const struct regmap_config max14577_regmap_config = { | 83 | static bool max77836_muic_volatile_reg(struct device *dev, unsigned int reg) |
84 | { | ||
85 | /* Any max14577 volatile registers are also max77836 volatile. */ | ||
86 | if (max14577_muic_volatile_reg(dev, reg)) | ||
87 | return true; | ||
88 | |||
89 | switch (reg) { | ||
90 | case MAX77836_FG_REG_VCELL_MSB ... MAX77836_FG_REG_SOC_LSB: | ||
91 | case MAX77836_FG_REG_CRATE_MSB ... MAX77836_FG_REG_CRATE_LSB: | ||
92 | case MAX77836_FG_REG_STATUS_H ... MAX77836_FG_REG_STATUS_L: | ||
93 | case MAX77836_PMIC_REG_INTSRC: | ||
94 | case MAX77836_PMIC_REG_TOPSYS_INT: | ||
95 | case MAX77836_PMIC_REG_TOPSYS_STAT: | ||
96 | return true; | ||
97 | default: | ||
98 | break; | ||
99 | } | ||
100 | return false; | ||
101 | } | ||
102 | |||
103 | static const struct regmap_config max14577_muic_regmap_config = { | ||
52 | .reg_bits = 8, | 104 | .reg_bits = 8, |
53 | .val_bits = 8, | 105 | .val_bits = 8, |
54 | .volatile_reg = max14577_volatile_reg, | 106 | .volatile_reg = max14577_muic_volatile_reg, |
55 | .max_register = MAX14577_REG_END, | 107 | .max_register = MAX14577_REG_END, |
56 | }; | 108 | }; |
57 | 109 | ||
110 | static const struct regmap_config max77836_pmic_regmap_config = { | ||
111 | .reg_bits = 8, | ||
112 | .val_bits = 8, | ||
113 | .volatile_reg = max77836_muic_volatile_reg, | ||
114 | .max_register = MAX77836_PMIC_REG_END, | ||
115 | }; | ||
116 | |||
58 | static const struct regmap_irq max14577_irqs[] = { | 117 | static const struct regmap_irq max14577_irqs[] = { |
59 | /* INT1 interrupts */ | 118 | /* INT1 interrupts */ |
60 | { .reg_offset = 0, .mask = INT1_ADC_MASK, }, | 119 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, |
61 | { .reg_offset = 0, .mask = INT1_ADCLOW_MASK, }, | 120 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, |
62 | { .reg_offset = 0, .mask = INT1_ADCERR_MASK, }, | 121 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, |
63 | /* INT2 interrupts */ | 122 | /* INT2 interrupts */ |
64 | { .reg_offset = 1, .mask = INT2_CHGTYP_MASK, }, | 123 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, |
65 | { .reg_offset = 1, .mask = INT2_CHGDETRUN_MASK, }, | 124 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, |
66 | { .reg_offset = 1, .mask = INT2_DCDTMR_MASK, }, | 125 | { .reg_offset = 1, .mask = MAX14577_INT2_DCDTMR_MASK, }, |
67 | { .reg_offset = 1, .mask = INT2_DBCHG_MASK, }, | 126 | { .reg_offset = 1, .mask = MAX14577_INT2_DBCHG_MASK, }, |
68 | { .reg_offset = 1, .mask = INT2_VBVOLT_MASK, }, | 127 | { .reg_offset = 1, .mask = MAX14577_INT2_VBVOLT_MASK, }, |
69 | /* INT3 interrupts */ | 128 | /* INT3 interrupts */ |
70 | { .reg_offset = 2, .mask = INT3_EOC_MASK, }, | 129 | { .reg_offset = 2, .mask = MAX14577_INT3_EOC_MASK, }, |
71 | { .reg_offset = 2, .mask = INT3_CGMBC_MASK, }, | 130 | { .reg_offset = 2, .mask = MAX14577_INT3_CGMBC_MASK, }, |
72 | { .reg_offset = 2, .mask = INT3_OVP_MASK, }, | 131 | { .reg_offset = 2, .mask = MAX14577_INT3_OVP_MASK, }, |
73 | { .reg_offset = 2, .mask = INT3_MBCCHGERR_MASK, }, | 132 | { .reg_offset = 2, .mask = MAX14577_INT3_MBCCHGERR_MASK, }, |
74 | }; | 133 | }; |
75 | 134 | ||
76 | static const struct regmap_irq_chip max14577_irq_chip = { | 135 | static const struct regmap_irq_chip max14577_irq_chip = { |
77 | .name = "max14577", | 136 | .name = "max14577", |
78 | .status_base = MAX14577_REG_INT1, | 137 | .status_base = MAX14577_REG_INT1, |
79 | .mask_base = MAX14577_REG_INTMASK1, | 138 | .mask_base = MAX14577_REG_INTMASK1, |
80 | .mask_invert = 1, | 139 | .mask_invert = true, |
81 | .num_regs = 3, | 140 | .num_regs = 3, |
82 | .irqs = max14577_irqs, | 141 | .irqs = max14577_irqs, |
83 | .num_irqs = ARRAY_SIZE(max14577_irqs), | 142 | .num_irqs = ARRAY_SIZE(max14577_irqs), |
84 | }; | 143 | }; |
85 | 144 | ||
145 | static const struct regmap_irq max77836_muic_irqs[] = { | ||
146 | /* INT1 interrupts */ | ||
147 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, | ||
148 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, | ||
149 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, | ||
150 | { .reg_offset = 0, .mask = MAX77836_INT1_ADC1K_MASK, }, | ||
151 | /* INT2 interrupts */ | ||
152 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, | ||
153 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, | ||
154 | { .reg_offset = 1, .mask = MAX14577_INT2_DCDTMR_MASK, }, | ||
155 | { .reg_offset = 1, .mask = MAX14577_INT2_DBCHG_MASK, }, | ||
156 | { .reg_offset = 1, .mask = MAX14577_INT2_VBVOLT_MASK, }, | ||
157 | { .reg_offset = 1, .mask = MAX77836_INT2_VIDRM_MASK, }, | ||
158 | /* INT3 interrupts */ | ||
159 | { .reg_offset = 2, .mask = MAX14577_INT3_EOC_MASK, }, | ||
160 | { .reg_offset = 2, .mask = MAX14577_INT3_CGMBC_MASK, }, | ||
161 | { .reg_offset = 2, .mask = MAX14577_INT3_OVP_MASK, }, | ||
162 | { .reg_offset = 2, .mask = MAX14577_INT3_MBCCHGERR_MASK, }, | ||
163 | }; | ||
164 | |||
165 | static const struct regmap_irq_chip max77836_muic_irq_chip = { | ||
166 | .name = "max77836-muic", | ||
167 | .status_base = MAX14577_REG_INT1, | ||
168 | .mask_base = MAX14577_REG_INTMASK1, | ||
169 | .mask_invert = true, | ||
170 | .num_regs = 3, | ||
171 | .irqs = max77836_muic_irqs, | ||
172 | .num_irqs = ARRAY_SIZE(max77836_muic_irqs), | ||
173 | }; | ||
174 | |||
175 | static const struct regmap_irq max77836_pmic_irqs[] = { | ||
176 | { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T120C_MASK, }, | ||
177 | { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T140C_MASK, }, | ||
178 | }; | ||
179 | |||
180 | static const struct regmap_irq_chip max77836_pmic_irq_chip = { | ||
181 | .name = "max77836-pmic", | ||
182 | .status_base = MAX77836_PMIC_REG_TOPSYS_INT, | ||
183 | .mask_base = MAX77836_PMIC_REG_TOPSYS_INT_MASK, | ||
184 | .mask_invert = false, | ||
185 | .num_regs = 1, | ||
186 | .irqs = max77836_pmic_irqs, | ||
187 | .num_irqs = ARRAY_SIZE(max77836_pmic_irqs), | ||
188 | }; | ||
189 | |||
190 | static void max14577_print_dev_type(struct max14577 *max14577) | ||
191 | { | ||
192 | u8 reg_data, vendor_id, device_id; | ||
193 | int ret; | ||
194 | |||
195 | ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID, | ||
196 | ®_data); | ||
197 | if (ret) { | ||
198 | dev_err(max14577->dev, | ||
199 | "Failed to read DEVICEID register: %d\n", ret); | ||
200 | return; | ||
201 | } | ||
202 | |||
203 | vendor_id = ((reg_data & DEVID_VENDORID_MASK) >> | ||
204 | DEVID_VENDORID_SHIFT); | ||
205 | device_id = ((reg_data & DEVID_DEVICEID_MASK) >> | ||
206 | DEVID_DEVICEID_SHIFT); | ||
207 | |||
208 | dev_info(max14577->dev, "Device type: %u (ID: 0x%x, vendor: 0x%x)\n", | ||
209 | max14577->dev_type, device_id, vendor_id); | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Max77836 specific initialization code for driver probe. | ||
214 | * Adds new I2C dummy device, regmap and regmap IRQ chip. | ||
215 | * Unmasks Interrupt Source register. | ||
216 | * | ||
217 | * On success returns 0. | ||
218 | * On failure returns errno and reverts any changes done so far (e.g. remove | ||
219 | * I2C dummy device), except masking the INT SRC register. | ||
220 | */ | ||
221 | static int max77836_init(struct max14577 *max14577) | ||
222 | { | ||
223 | int ret; | ||
224 | u8 intsrc_mask; | ||
225 | |||
226 | max14577->i2c_pmic = i2c_new_dummy(max14577->i2c->adapter, | ||
227 | I2C_ADDR_PMIC); | ||
228 | if (!max14577->i2c_pmic) { | ||
229 | dev_err(max14577->dev, "Failed to register PMIC I2C device\n"); | ||
230 | return -ENODEV; | ||
231 | } | ||
232 | i2c_set_clientdata(max14577->i2c_pmic, max14577); | ||
233 | |||
234 | max14577->regmap_pmic = devm_regmap_init_i2c(max14577->i2c_pmic, | ||
235 | &max77836_pmic_regmap_config); | ||
236 | if (IS_ERR(max14577->regmap_pmic)) { | ||
237 | ret = PTR_ERR(max14577->regmap_pmic); | ||
238 | dev_err(max14577->dev, "Failed to allocate PMIC register map: %d\n", | ||
239 | ret); | ||
240 | goto err; | ||
241 | } | ||
242 | |||
243 | /* Un-mask MAX77836 Interrupt Source register */ | ||
244 | ret = max14577_read_reg(max14577->regmap_pmic, | ||
245 | MAX77836_PMIC_REG_INTSRC_MASK, &intsrc_mask); | ||
246 | if (ret < 0) { | ||
247 | dev_err(max14577->dev, "Failed to read PMIC register\n"); | ||
248 | goto err; | ||
249 | } | ||
250 | |||
251 | intsrc_mask &= ~(MAX77836_INTSRC_MASK_TOP_INT_MASK); | ||
252 | intsrc_mask &= ~(MAX77836_INTSRC_MASK_MUIC_CHG_INT_MASK); | ||
253 | ret = max14577_write_reg(max14577->regmap_pmic, | ||
254 | MAX77836_PMIC_REG_INTSRC_MASK, intsrc_mask); | ||
255 | if (ret < 0) { | ||
256 | dev_err(max14577->dev, "Failed to write PMIC register\n"); | ||
257 | goto err; | ||
258 | } | ||
259 | |||
260 | ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq, | ||
261 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, | ||
262 | 0, &max77836_pmic_irq_chip, | ||
263 | &max14577->irq_data_pmic); | ||
264 | if (ret != 0) { | ||
265 | dev_err(max14577->dev, "Failed to request PMIC IRQ %d: %d\n", | ||
266 | max14577->irq, ret); | ||
267 | goto err; | ||
268 | } | ||
269 | |||
270 | return 0; | ||
271 | |||
272 | err: | ||
273 | i2c_unregister_device(max14577->i2c_pmic); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Max77836 specific de-initialization code for driver remove. | ||
280 | */ | ||
281 | static void max77836_remove(struct max14577 *max14577) | ||
282 | { | ||
283 | regmap_del_irq_chip(max14577->irq, max14577->irq_data_pmic); | ||
284 | i2c_unregister_device(max14577->i2c_pmic); | ||
285 | } | ||
286 | |||
86 | static int max14577_i2c_probe(struct i2c_client *i2c, | 287 | static int max14577_i2c_probe(struct i2c_client *i2c, |
87 | const struct i2c_device_id *id) | 288 | const struct i2c_device_id *id) |
88 | { | 289 | { |
89 | struct max14577 *max14577; | 290 | struct max14577 *max14577; |
90 | struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); | 291 | struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); |
91 | struct device_node *np = i2c->dev.of_node; | 292 | struct device_node *np = i2c->dev.of_node; |
92 | u8 reg_data; | ||
93 | int ret = 0; | 293 | int ret = 0; |
294 | const struct regmap_irq_chip *irq_chip; | ||
295 | struct mfd_cell *mfd_devs; | ||
296 | unsigned int mfd_devs_size; | ||
297 | int irq_flags; | ||
94 | 298 | ||
95 | if (np) { | 299 | if (np) { |
96 | pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); | 300 | pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); |
@@ -113,7 +317,8 @@ static int max14577_i2c_probe(struct i2c_client *i2c, | |||
113 | max14577->i2c = i2c; | 317 | max14577->i2c = i2c; |
114 | max14577->irq = i2c->irq; | 318 | max14577->irq = i2c->irq; |
115 | 319 | ||
116 | max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config); | 320 | max14577->regmap = devm_regmap_init_i2c(i2c, |
321 | &max14577_muic_regmap_config); | ||
117 | if (IS_ERR(max14577->regmap)) { | 322 | if (IS_ERR(max14577->regmap)) { |
118 | ret = PTR_ERR(max14577->regmap); | 323 | ret = PTR_ERR(max14577->regmap); |
119 | dev_err(max14577->dev, "Failed to allocate register map: %d\n", | 324 | dev_err(max14577->dev, "Failed to allocate register map: %d\n", |
@@ -121,23 +326,36 @@ static int max14577_i2c_probe(struct i2c_client *i2c, | |||
121 | return ret; | 326 | return ret; |
122 | } | 327 | } |
123 | 328 | ||
124 | ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID, | 329 | if (np) { |
125 | ®_data); | 330 | const struct of_device_id *of_id; |
126 | if (ret) { | 331 | |
127 | dev_err(max14577->dev, "Device not found on this channel: %d\n", | 332 | of_id = of_match_device(max14577_dt_match, &i2c->dev); |
128 | ret); | 333 | if (of_id) |
129 | return ret; | 334 | max14577->dev_type = (unsigned int)of_id->data; |
335 | } else { | ||
336 | max14577->dev_type = id->driver_data; | ||
337 | } | ||
338 | |||
339 | max14577_print_dev_type(max14577); | ||
340 | |||
341 | switch (max14577->dev_type) { | ||
342 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
343 | irq_chip = &max77836_muic_irq_chip; | ||
344 | mfd_devs = max77836_devs; | ||
345 | mfd_devs_size = ARRAY_SIZE(max77836_devs); | ||
346 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED; | ||
347 | break; | ||
348 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
349 | default: | ||
350 | irq_chip = &max14577_irq_chip; | ||
351 | mfd_devs = max14577_devs; | ||
352 | mfd_devs_size = ARRAY_SIZE(max14577_devs); | ||
353 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | ||
354 | break; | ||
130 | } | 355 | } |
131 | max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >> | ||
132 | DEVID_VENDORID_SHIFT); | ||
133 | max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >> | ||
134 | DEVID_DEVICEID_SHIFT); | ||
135 | dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n", | ||
136 | max14577->device_id, max14577->vendor_id); | ||
137 | 356 | ||
138 | ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, | 357 | ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, |
139 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, | 358 | irq_flags, 0, irq_chip, |
140 | &max14577_irq_chip, | ||
141 | &max14577->irq_data); | 359 | &max14577->irq_data); |
142 | if (ret != 0) { | 360 | if (ret != 0) { |
143 | dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", | 361 | dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", |
@@ -145,8 +363,15 @@ static int max14577_i2c_probe(struct i2c_client *i2c, | |||
145 | return ret; | 363 | return ret; |
146 | } | 364 | } |
147 | 365 | ||
148 | ret = mfd_add_devices(max14577->dev, -1, max14577_devs, | 366 | /* Max77836 specific initialization code (additional regmap) */ |
149 | ARRAY_SIZE(max14577_devs), NULL, 0, | 367 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) { |
368 | ret = max77836_init(max14577); | ||
369 | if (ret < 0) | ||
370 | goto err_max77836; | ||
371 | } | ||
372 | |||
373 | ret = mfd_add_devices(max14577->dev, -1, mfd_devs, | ||
374 | mfd_devs_size, NULL, 0, | ||
150 | regmap_irq_get_domain(max14577->irq_data)); | 375 | regmap_irq_get_domain(max14577->irq_data)); |
151 | if (ret < 0) | 376 | if (ret < 0) |
152 | goto err_mfd; | 377 | goto err_mfd; |
@@ -156,6 +381,9 @@ static int max14577_i2c_probe(struct i2c_client *i2c, | |||
156 | return 0; | 381 | return 0; |
157 | 382 | ||
158 | err_mfd: | 383 | err_mfd: |
384 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) | ||
385 | max77836_remove(max14577); | ||
386 | err_max77836: | ||
159 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); | 387 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); |
160 | 388 | ||
161 | return ret; | 389 | return ret; |
@@ -167,12 +395,15 @@ static int max14577_i2c_remove(struct i2c_client *i2c) | |||
167 | 395 | ||
168 | mfd_remove_devices(max14577->dev); | 396 | mfd_remove_devices(max14577->dev); |
169 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); | 397 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); |
398 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) | ||
399 | max77836_remove(max14577); | ||
170 | 400 | ||
171 | return 0; | 401 | return 0; |
172 | } | 402 | } |
173 | 403 | ||
174 | static const struct i2c_device_id max14577_i2c_id[] = { | 404 | static const struct i2c_device_id max14577_i2c_id[] = { |
175 | { "max14577", 0 }, | 405 | { "max14577", MAXIM_DEVICE_TYPE_MAX14577, }, |
406 | { "max77836", MAXIM_DEVICE_TYPE_MAX77836, }, | ||
176 | { } | 407 | { } |
177 | }; | 408 | }; |
178 | MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); | 409 | MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); |
@@ -215,11 +446,6 @@ static int max14577_resume(struct device *dev) | |||
215 | } | 446 | } |
216 | #endif /* CONFIG_PM_SLEEP */ | 447 | #endif /* CONFIG_PM_SLEEP */ |
217 | 448 | ||
218 | static struct of_device_id max14577_dt_match[] = { | ||
219 | { .compatible = "maxim,max14577", }, | ||
220 | {}, | ||
221 | }; | ||
222 | |||
223 | static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume); | 449 | static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume); |
224 | 450 | ||
225 | static struct i2c_driver max14577_i2c_driver = { | 451 | static struct i2c_driver max14577_i2c_driver = { |
@@ -236,6 +462,9 @@ static struct i2c_driver max14577_i2c_driver = { | |||
236 | 462 | ||
237 | static int __init max14577_i2c_init(void) | 463 | static int __init max14577_i2c_init(void) |
238 | { | 464 | { |
465 | BUILD_BUG_ON(ARRAY_SIZE(max14577_i2c_id) != MAXIM_DEVICE_TYPE_NUM); | ||
466 | BUILD_BUG_ON(ARRAY_SIZE(max14577_dt_match) != MAXIM_DEVICE_TYPE_NUM); | ||
467 | |||
239 | return i2c_add_driver(&max14577_i2c_driver); | 468 | return i2c_add_driver(&max14577_i2c_driver); |
240 | } | 469 | } |
241 | subsys_initcall(max14577_i2c_init); | 470 | subsys_initcall(max14577_i2c_init); |
@@ -247,5 +476,5 @@ static void __exit max14577_i2c_exit(void) | |||
247 | module_exit(max14577_i2c_exit); | 476 | module_exit(max14577_i2c_exit); |
248 | 477 | ||
249 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); | 478 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
250 | MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver"); | 479 | MODULE_DESCRIPTION("Maxim 14577/77836 multi-function core driver"); |
251 | MODULE_LICENSE("GPL"); | 480 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 06e64b6fcb89..0c6c21c5b1a8 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -673,9 +673,13 @@ int mc13xxx_common_init(struct device *dev) | |||
673 | if (mc13xxx->flags & MC13XXX_USE_ADC) | 673 | if (mc13xxx->flags & MC13XXX_USE_ADC) |
674 | mc13xxx_add_subdevice(mc13xxx, "%s-adc"); | 674 | mc13xxx_add_subdevice(mc13xxx, "%s-adc"); |
675 | 675 | ||
676 | if (mc13xxx->flags & MC13XXX_USE_CODEC) | 676 | if (mc13xxx->flags & MC13XXX_USE_CODEC) { |
677 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec", | 677 | if (pdata) |
678 | pdata->codec, sizeof(*pdata->codec)); | 678 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec", |
679 | pdata->codec, sizeof(*pdata->codec)); | ||
680 | else | ||
681 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); | ||
682 | } | ||
679 | 683 | ||
680 | if (mc13xxx->flags & MC13XXX_USE_RTC) | 684 | if (mc13xxx->flags & MC13XXX_USE_RTC) |
681 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); | 685 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); |
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c index b53b9d46cc45..141ea52c46e3 100644 --- a/drivers/mfd/rtsx_usb.c +++ b/drivers/mfd/rtsx_usb.c | |||
@@ -67,7 +67,7 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, | |||
67 | ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); | 67 | ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); |
68 | add_timer(&ucr->sg_timer); | 68 | add_timer(&ucr->sg_timer); |
69 | usb_sg_wait(&ucr->current_sg); | 69 | usb_sg_wait(&ucr->current_sg); |
70 | del_timer(&ucr->sg_timer); | 70 | del_timer_sync(&ucr->sg_timer); |
71 | 71 | ||
72 | if (act_len) | 72 | if (act_len) |
73 | *act_len = ucr->current_sg.bytes; | 73 | *act_len = ucr->current_sg.bytes; |
@@ -644,14 +644,14 @@ static int rtsx_usb_probe(struct usb_interface *intf, | |||
644 | if (ret) | 644 | if (ret) |
645 | goto out_init_fail; | 645 | goto out_init_fail; |
646 | 646 | ||
647 | /* initialize USB SG transfer timer */ | ||
648 | setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr); | ||
649 | |||
647 | ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells, | 650 | ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells, |
648 | ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL); | 651 | ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL); |
649 | if (ret) | 652 | if (ret) |
650 | goto out_init_fail; | 653 | goto out_init_fail; |
651 | 654 | ||
652 | /* initialize USB SG transfer timer */ | ||
653 | init_timer(&ucr->sg_timer); | ||
654 | setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr); | ||
655 | #ifdef CONFIG_PM | 655 | #ifdef CONFIG_PM |
656 | intf->needs_remote_wakeup = 1; | 656 | intf->needs_remote_wakeup = 1; |
657 | usb_enable_autosuspend(usb_dev); | 657 | usb_enable_autosuspend(usb_dev); |
@@ -687,9 +687,15 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message) | |||
687 | dev_dbg(&intf->dev, "%s called with pm message 0x%04u\n", | 687 | dev_dbg(&intf->dev, "%s called with pm message 0x%04u\n", |
688 | __func__, message.event); | 688 | __func__, message.event); |
689 | 689 | ||
690 | /* | ||
691 | * Call to make sure LED is off during suspend to save more power. | ||
692 | * It is NOT a permanent state and could be turned on anytime later. | ||
693 | * Thus no need to call turn_on when resunming. | ||
694 | */ | ||
690 | mutex_lock(&ucr->dev_mutex); | 695 | mutex_lock(&ucr->dev_mutex); |
691 | rtsx_usb_turn_off_led(ucr); | 696 | rtsx_usb_turn_off_led(ucr); |
692 | mutex_unlock(&ucr->dev_mutex); | 697 | mutex_unlock(&ucr->dev_mutex); |
698 | |||
693 | return 0; | 699 | return 0; |
694 | } | 700 | } |
695 | 701 | ||
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 0da02e11d58e..a45f9c0a330a 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/of_device.h> | ||
17 | #include "stmpe.h" | 18 | #include "stmpe.h" |
18 | 19 | ||
19 | static int i2c_reg_read(struct stmpe *stmpe, u8 reg) | 20 | static int i2c_reg_read(struct stmpe *stmpe, u8 reg) |
@@ -52,15 +53,41 @@ static struct stmpe_client_info i2c_ci = { | |||
52 | .write_block = i2c_block_write, | 53 | .write_block = i2c_block_write, |
53 | }; | 54 | }; |
54 | 55 | ||
56 | static const struct of_device_id stmpe_of_match[] = { | ||
57 | { .compatible = "st,stmpe610", .data = (void *)STMPE610, }, | ||
58 | { .compatible = "st,stmpe801", .data = (void *)STMPE801, }, | ||
59 | { .compatible = "st,stmpe811", .data = (void *)STMPE811, }, | ||
60 | { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, }, | ||
61 | { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, }, | ||
62 | { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, }, | ||
63 | { .compatible = "st,stmpe2403", .data = (void *)STMPE2403, }, | ||
64 | {}, | ||
65 | }; | ||
66 | MODULE_DEVICE_TABLE(of, stmpe_of_match); | ||
67 | |||
55 | static int | 68 | static int |
56 | stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | 69 | stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) |
57 | { | 70 | { |
71 | int partnum; | ||
72 | const struct of_device_id *of_id; | ||
73 | |||
58 | i2c_ci.data = (void *)id; | 74 | i2c_ci.data = (void *)id; |
59 | i2c_ci.irq = i2c->irq; | 75 | i2c_ci.irq = i2c->irq; |
60 | i2c_ci.client = i2c; | 76 | i2c_ci.client = i2c; |
61 | i2c_ci.dev = &i2c->dev; | 77 | i2c_ci.dev = &i2c->dev; |
62 | 78 | ||
63 | return stmpe_probe(&i2c_ci, id->driver_data); | 79 | of_id = of_match_device(stmpe_of_match, &i2c->dev); |
80 | if (!of_id) { | ||
81 | /* | ||
82 | * This happens when the I2C ID matches the node name | ||
83 | * but no real compatible string has been given. | ||
84 | */ | ||
85 | dev_info(&i2c->dev, "matching on node name, compatible is preferred\n"); | ||
86 | partnum = id->driver_data; | ||
87 | } else | ||
88 | partnum = (int)of_id->data; | ||
89 | |||
90 | return stmpe_probe(&i2c_ci, partnum); | ||
64 | } | 91 | } |
65 | 92 | ||
66 | static int stmpe_i2c_remove(struct i2c_client *i2c) | 93 | static int stmpe_i2c_remove(struct i2c_client *i2c) |
@@ -89,6 +116,7 @@ static struct i2c_driver stmpe_i2c_driver = { | |||
89 | #ifdef CONFIG_PM | 116 | #ifdef CONFIG_PM |
90 | .pm = &stmpe_dev_pm_ops, | 117 | .pm = &stmpe_dev_pm_ops, |
91 | #endif | 118 | #endif |
119 | .of_match_table = stmpe_of_match, | ||
92 | }, | 120 | }, |
93 | .probe = stmpe_i2c_probe, | 121 | .probe = stmpe_i2c_probe, |
94 | .remove = stmpe_i2c_remove, | 122 | .remove = stmpe_i2c_remove, |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 4a91f6771fb8..3b6bfa7184ad 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/mfd/core.h> | 21 | #include <linux/mfd/core.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/regulator/consumer.h> | ||
23 | #include "stmpe.h" | 24 | #include "stmpe.h" |
24 | 25 | ||
25 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | 26 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) |
@@ -605,9 +606,18 @@ static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, | |||
605 | 606 | ||
606 | if (blocks & STMPE_BLOCK_GPIO) | 607 | if (blocks & STMPE_BLOCK_GPIO) |
607 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; | 608 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; |
609 | else | ||
610 | mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO; | ||
608 | 611 | ||
609 | if (blocks & STMPE_BLOCK_KEYPAD) | 612 | if (blocks & STMPE_BLOCK_KEYPAD) |
610 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; | 613 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; |
614 | else | ||
615 | mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC; | ||
616 | |||
617 | if (blocks & STMPE_BLOCK_PWM) | ||
618 | mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM; | ||
619 | else | ||
620 | mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM; | ||
611 | 621 | ||
612 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, | 622 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, |
613 | enable ? mask : 0); | 623 | enable ? mask : 0); |
@@ -986,9 +996,6 @@ static int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np) | |||
986 | int base = 0; | 996 | int base = 0; |
987 | int num_irqs = stmpe->variant->num_irqs; | 997 | int num_irqs = stmpe->variant->num_irqs; |
988 | 998 | ||
989 | if (!np) | ||
990 | base = stmpe->irq_base; | ||
991 | |||
992 | stmpe->domain = irq_domain_add_simple(np, num_irqs, base, | 999 | stmpe->domain = irq_domain_add_simple(np, num_irqs, base, |
993 | &stmpe_irq_ops, stmpe); | 1000 | &stmpe_irq_ops, stmpe); |
994 | if (!stmpe->domain) { | 1001 | if (!stmpe->domain) { |
@@ -1067,7 +1074,7 @@ static int stmpe_chip_init(struct stmpe *stmpe) | |||
1067 | static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell) | 1074 | static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell) |
1068 | { | 1075 | { |
1069 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, | 1076 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, |
1070 | NULL, stmpe->irq_base, stmpe->domain); | 1077 | NULL, 0, stmpe->domain); |
1071 | } | 1078 | } |
1072 | 1079 | ||
1073 | static int stmpe_devices_init(struct stmpe *stmpe) | 1080 | static int stmpe_devices_init(struct stmpe *stmpe) |
@@ -1171,12 +1178,23 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
1171 | stmpe->dev = ci->dev; | 1178 | stmpe->dev = ci->dev; |
1172 | stmpe->client = ci->client; | 1179 | stmpe->client = ci->client; |
1173 | stmpe->pdata = pdata; | 1180 | stmpe->pdata = pdata; |
1174 | stmpe->irq_base = pdata->irq_base; | ||
1175 | stmpe->ci = ci; | 1181 | stmpe->ci = ci; |
1176 | stmpe->partnum = partnum; | 1182 | stmpe->partnum = partnum; |
1177 | stmpe->variant = stmpe_variant_info[partnum]; | 1183 | stmpe->variant = stmpe_variant_info[partnum]; |
1178 | stmpe->regs = stmpe->variant->regs; | 1184 | stmpe->regs = stmpe->variant->regs; |
1179 | stmpe->num_gpios = stmpe->variant->num_gpios; | 1185 | stmpe->num_gpios = stmpe->variant->num_gpios; |
1186 | stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc"); | ||
1187 | if (!IS_ERR(stmpe->vcc)) { | ||
1188 | ret = regulator_enable(stmpe->vcc); | ||
1189 | if (ret) | ||
1190 | dev_warn(ci->dev, "failed to enable VCC supply\n"); | ||
1191 | } | ||
1192 | stmpe->vio = devm_regulator_get_optional(ci->dev, "vio"); | ||
1193 | if (!IS_ERR(stmpe->vio)) { | ||
1194 | ret = regulator_enable(stmpe->vio); | ||
1195 | if (ret) | ||
1196 | dev_warn(ci->dev, "failed to enable VIO supply\n"); | ||
1197 | } | ||
1180 | dev_set_drvdata(stmpe->dev, stmpe); | 1198 | dev_set_drvdata(stmpe->dev, stmpe); |
1181 | 1199 | ||
1182 | if (ci->init) | 1200 | if (ci->init) |
@@ -1243,6 +1261,11 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
1243 | 1261 | ||
1244 | int stmpe_remove(struct stmpe *stmpe) | 1262 | int stmpe_remove(struct stmpe *stmpe) |
1245 | { | 1263 | { |
1264 | if (!IS_ERR(stmpe->vio)) | ||
1265 | regulator_disable(stmpe->vio); | ||
1266 | if (!IS_ERR(stmpe->vcc)) | ||
1267 | regulator_disable(stmpe->vcc); | ||
1268 | |||
1246 | mfd_remove_devices(stmpe->dev); | 1269 | mfd_remove_devices(stmpe->dev); |
1247 | 1270 | ||
1248 | return 0; | 1271 | return 0; |
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h index 6639f1b0fef5..9e4d21d37a11 100644 --- a/drivers/mfd/stmpe.h +++ b/drivers/mfd/stmpe.h | |||
@@ -192,7 +192,7 @@ int stmpe_remove(struct stmpe *stmpe); | |||
192 | 192 | ||
193 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | 193 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) |
194 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) | 194 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) |
195 | #define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0) | 195 | #define STMPE1601_SYS_CTRL_ENABLE_SPWM (1 << 0) |
196 | 196 | ||
197 | /* The 1601/2403 share the same masks */ | 197 | /* The 1601/2403 share the same masks */ |
198 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) | 198 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) |
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index ba1a25d758c1..1c3e6e2efe41 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c | |||
@@ -32,14 +32,6 @@ | |||
32 | #define NUM_INT_REG 2 | 32 | #define NUM_INT_REG 2 |
33 | #define TOTAL_NUM_REG 0x18 | 33 | #define TOTAL_NUM_REG 0x18 |
34 | 34 | ||
35 | /* interrupt status registers */ | ||
36 | #define TPS65090_INT_STS 0x0 | ||
37 | #define TPS65090_INT_STS2 0x1 | ||
38 | |||
39 | /* interrupt mask registers */ | ||
40 | #define TPS65090_INT_MSK 0x2 | ||
41 | #define TPS65090_INT_MSK2 0x3 | ||
42 | |||
43 | #define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1 | 35 | #define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1 |
44 | #define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2 | 36 | #define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2 |
45 | #define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3 | 37 | #define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3 |
@@ -64,11 +56,16 @@ static struct resource charger_resources[] = { | |||
64 | } | 56 | } |
65 | }; | 57 | }; |
66 | 58 | ||
67 | static const struct mfd_cell tps65090s[] = { | 59 | enum tps65090_cells { |
68 | { | 60 | PMIC = 0, |
61 | CHARGER = 1, | ||
62 | }; | ||
63 | |||
64 | static struct mfd_cell tps65090s[] = { | ||
65 | [PMIC] = { | ||
69 | .name = "tps65090-pmic", | 66 | .name = "tps65090-pmic", |
70 | }, | 67 | }, |
71 | { | 68 | [CHARGER] = { |
72 | .name = "tps65090-charger", | 69 | .name = "tps65090-charger", |
73 | .num_resources = ARRAY_SIZE(charger_resources), | 70 | .num_resources = ARRAY_SIZE(charger_resources), |
74 | .resources = &charger_resources[0], | 71 | .resources = &charger_resources[0], |
@@ -139,17 +136,26 @@ static struct regmap_irq_chip tps65090_irq_chip = { | |||
139 | .irqs = tps65090_irqs, | 136 | .irqs = tps65090_irqs, |
140 | .num_irqs = ARRAY_SIZE(tps65090_irqs), | 137 | .num_irqs = ARRAY_SIZE(tps65090_irqs), |
141 | .num_regs = NUM_INT_REG, | 138 | .num_regs = NUM_INT_REG, |
142 | .status_base = TPS65090_INT_STS, | 139 | .status_base = TPS65090_REG_INTR_STS, |
143 | .mask_base = TPS65090_INT_MSK, | 140 | .mask_base = TPS65090_REG_INTR_MASK, |
144 | .mask_invert = true, | 141 | .mask_invert = true, |
145 | }; | 142 | }; |
146 | 143 | ||
147 | static bool is_volatile_reg(struct device *dev, unsigned int reg) | 144 | static bool is_volatile_reg(struct device *dev, unsigned int reg) |
148 | { | 145 | { |
149 | if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS2)) | 146 | /* Nearly all registers have status bits mixed in, except a few */ |
150 | return true; | 147 | switch (reg) { |
151 | else | 148 | case TPS65090_REG_INTR_MASK: |
149 | case TPS65090_REG_INTR_MASK2: | ||
150 | case TPS65090_REG_CG_CTRL0: | ||
151 | case TPS65090_REG_CG_CTRL1: | ||
152 | case TPS65090_REG_CG_CTRL2: | ||
153 | case TPS65090_REG_CG_CTRL3: | ||
154 | case TPS65090_REG_CG_CTRL4: | ||
155 | case TPS65090_REG_CG_CTRL5: | ||
152 | return false; | 156 | return false; |
157 | } | ||
158 | return true; | ||
153 | } | 159 | } |
154 | 160 | ||
155 | static const struct regmap_config tps65090_regmap_config = { | 161 | static const struct regmap_config tps65090_regmap_config = { |
@@ -211,6 +217,9 @@ static int tps65090_i2c_probe(struct i2c_client *client, | |||
211 | "IRQ init failed with err: %d\n", ret); | 217 | "IRQ init failed with err: %d\n", ret); |
212 | return ret; | 218 | return ret; |
213 | } | 219 | } |
220 | } else { | ||
221 | /* Don't tell children they have an IRQ that'll never fire */ | ||
222 | tps65090s[CHARGER].num_resources = 0; | ||
214 | } | 223 | } |
215 | 224 | ||
216 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, | 225 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index bbd54414a75d..835e5549ecdd 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c | |||
@@ -495,6 +495,10 @@ static void tps6586x_print_version(struct i2c_client *client, int version) | |||
495 | case TPS658623: | 495 | case TPS658623: |
496 | name = "TPS658623"; | 496 | name = "TPS658623"; |
497 | break; | 497 | break; |
498 | case TPS658640: | ||
499 | case TPS658640v2: | ||
500 | name = "TPS658640"; | ||
501 | break; | ||
498 | case TPS658643: | 502 | case TPS658643: |
499 | name = "TPS658643"; | 503 | name = "TPS658643"; |
500 | break; | 504 | break; |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e87140bef667..db11b4f40611 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -98,7 +98,11 @@ | |||
98 | #define TWL4030_BASEADD_BACKUP 0x0014 | 98 | #define TWL4030_BASEADD_BACKUP 0x0014 |
99 | #define TWL4030_BASEADD_INT 0x002E | 99 | #define TWL4030_BASEADD_INT 0x002E |
100 | #define TWL4030_BASEADD_PM_MASTER 0x0036 | 100 | #define TWL4030_BASEADD_PM_MASTER 0x0036 |
101 | |||
101 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B | 102 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B |
103 | #define TWL4030_DCDC_GLOBAL_CFG 0x06 | ||
104 | #define SMARTREFLEX_ENABLE BIT(3) | ||
105 | |||
102 | #define TWL4030_BASEADD_RTC 0x001C | 106 | #define TWL4030_BASEADD_RTC 0x001C |
103 | #define TWL4030_BASEADD_SECURED_REG 0x0000 | 107 | #define TWL4030_BASEADD_SECURED_REG 0x0000 |
104 | 108 | ||
@@ -1204,6 +1208,11 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1204 | * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. | 1208 | * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. |
1205 | * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, | 1209 | * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, |
1206 | * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. | 1210 | * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. |
1211 | * | ||
1212 | * Also, always enable SmartReflex bit as that's needed for omaps to | ||
1213 | * to do anything over I2C4 for voltage scaling even if SmartReflex | ||
1214 | * is disabled. Without the SmartReflex bit omap sys_clkreq idle | ||
1215 | * signal will never trigger for retention idle. | ||
1207 | */ | 1216 | */ |
1208 | if (twl_class_is_4030()) { | 1217 | if (twl_class_is_4030()) { |
1209 | u8 temp; | 1218 | u8 temp; |
@@ -1212,6 +1221,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1212 | temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ | 1221 | temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ |
1213 | I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); | 1222 | I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); |
1214 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); | 1223 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); |
1224 | |||
1225 | twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp, | ||
1226 | TWL4030_DCDC_GLOBAL_CFG); | ||
1227 | temp |= SMARTREFLEX_ENABLE; | ||
1228 | twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp, | ||
1229 | TWL4030_DCDC_GLOBAL_CFG); | ||
1215 | } | 1230 | } |
1216 | 1231 | ||
1217 | if (node) { | 1232 | if (node) { |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 8aaf8c1f3f63..b675882307e4 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -694,3 +694,10 @@ config MMC_REALTEK_PCI | |||
694 | help | 694 | help |
695 | Say Y here to include driver code to support SD/MMC card interface | 695 | Say Y here to include driver code to support SD/MMC card interface |
696 | of Realtek PCI-E card reader | 696 | of Realtek PCI-E card reader |
697 | |||
698 | config MMC_REALTEK_USB | ||
699 | tristate "Realtek USB SD/MMC Card Interface Driver" | ||
700 | depends on MFD_RTSX_USB | ||
701 | help | ||
702 | Say Y here to include driver code to support SD/MMC card interface | ||
703 | of Realtek RTS5129/39 series card reader | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 0c8aa5e1e304..3eb48b656f25 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -52,6 +52,7 @@ obj-$(CONFIG_MMC_USHC) += ushc.o | |||
52 | obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o | 52 | obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o |
53 | 53 | ||
54 | obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o | 54 | obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o |
55 | obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o | ||
55 | 56 | ||
56 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o | 57 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o |
57 | obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | 58 | obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o |
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c new file mode 100644 index 000000000000..e11fafa6fc6b --- /dev/null +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c | |||
@@ -0,0 +1,1455 @@ | |||
1 | /* Realtek USB SD/MMC Card Interface driver | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * Author: | ||
18 | * Roger Tseng <rogerable@realtek.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/mmc/host.h> | ||
27 | #include <linux/mmc/mmc.h> | ||
28 | #include <linux/mmc/sd.h> | ||
29 | #include <linux/mmc/sdio.h> | ||
30 | #include <linux/mmc/card.h> | ||
31 | #include <linux/scatterlist.h> | ||
32 | #include <linux/pm_runtime.h> | ||
33 | |||
34 | #include <linux/mfd/rtsx_usb.h> | ||
35 | #include <asm/unaligned.h> | ||
36 | |||
37 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) | ||
38 | #include <linux/leds.h> | ||
39 | #include <linux/workqueue.h> | ||
40 | #define RTSX_USB_USE_LEDS_CLASS | ||
41 | #endif | ||
42 | |||
43 | struct rtsx_usb_sdmmc { | ||
44 | struct platform_device *pdev; | ||
45 | struct rtsx_ucr *ucr; | ||
46 | struct mmc_host *mmc; | ||
47 | struct mmc_request *mrq; | ||
48 | |||
49 | struct mutex host_mutex; | ||
50 | |||
51 | u8 ssc_depth; | ||
52 | unsigned int clock; | ||
53 | bool vpclk; | ||
54 | bool double_clk; | ||
55 | bool host_removal; | ||
56 | bool card_exist; | ||
57 | bool initial_mode; | ||
58 | bool ddr_mode; | ||
59 | |||
60 | unsigned char power_mode; | ||
61 | |||
62 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) | ||
63 | struct led_classdev led; | ||
64 | char led_name[32]; | ||
65 | struct work_struct led_work; | ||
66 | #endif | ||
67 | }; | ||
68 | |||
69 | static inline struct device *sdmmc_dev(struct rtsx_usb_sdmmc *host) | ||
70 | { | ||
71 | return &(host->pdev->dev); | ||
72 | } | ||
73 | |||
74 | static inline void sd_clear_error(struct rtsx_usb_sdmmc *host) | ||
75 | { | ||
76 | struct rtsx_ucr *ucr = host->ucr; | ||
77 | rtsx_usb_ep0_write_register(ucr, CARD_STOP, | ||
78 | SD_STOP | SD_CLR_ERR, | ||
79 | SD_STOP | SD_CLR_ERR); | ||
80 | |||
81 | rtsx_usb_clear_dma_err(ucr); | ||
82 | rtsx_usb_clear_fsm_err(ucr); | ||
83 | } | ||
84 | |||
85 | #ifdef DEBUG | ||
86 | static void sd_print_debug_regs(struct rtsx_usb_sdmmc *host) | ||
87 | { | ||
88 | struct rtsx_ucr *ucr = host->ucr; | ||
89 | u8 val = 0; | ||
90 | |||
91 | rtsx_usb_ep0_read_register(ucr, SD_STAT1, &val); | ||
92 | dev_dbg(sdmmc_dev(host), "SD_STAT1: 0x%x\n", val); | ||
93 | rtsx_usb_ep0_read_register(ucr, SD_STAT2, &val); | ||
94 | dev_dbg(sdmmc_dev(host), "SD_STAT2: 0x%x\n", val); | ||
95 | rtsx_usb_ep0_read_register(ucr, SD_BUS_STAT, &val); | ||
96 | dev_dbg(sdmmc_dev(host), "SD_BUS_STAT: 0x%x\n", val); | ||
97 | } | ||
98 | #else | ||
99 | #define sd_print_debug_regs(host) | ||
100 | #endif /* DEBUG */ | ||
101 | |||
102 | static int sd_read_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, | ||
103 | u16 byte_cnt, u8 *buf, int buf_len, int timeout) | ||
104 | { | ||
105 | struct rtsx_ucr *ucr = host->ucr; | ||
106 | int err; | ||
107 | u8 trans_mode; | ||
108 | |||
109 | if (!buf) | ||
110 | buf_len = 0; | ||
111 | |||
112 | rtsx_usb_init_cmd(ucr); | ||
113 | if (cmd != NULL) { | ||
114 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__ | ||
115 | , cmd->opcode); | ||
116 | if (cmd->opcode == MMC_SEND_TUNING_BLOCK) | ||
117 | trans_mode = SD_TM_AUTO_TUNING; | ||
118 | else | ||
119 | trans_mode = SD_TM_NORMAL_READ; | ||
120 | |||
121 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
122 | SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); | ||
123 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
124 | SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); | ||
125 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
126 | SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); | ||
127 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
128 | SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); | ||
129 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
130 | SD_CMD4, 0xFF, (u8)cmd->arg); | ||
131 | } else { | ||
132 | trans_mode = SD_TM_AUTO_READ_3; | ||
133 | } | ||
134 | |||
135 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); | ||
136 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, | ||
137 | 0xFF, (u8)(byte_cnt >> 8)); | ||
138 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); | ||
139 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); | ||
140 | |||
141 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
142 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
143 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); | ||
144 | if (trans_mode != SD_TM_AUTO_TUNING) | ||
145 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
146 | CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); | ||
147 | |||
148 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, | ||
149 | 0xFF, trans_mode | SD_TRANSFER_START); | ||
150 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, | ||
151 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
152 | |||
153 | if (cmd != NULL) { | ||
154 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); | ||
155 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); | ||
156 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); | ||
157 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); | ||
158 | } | ||
159 | |||
160 | err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); | ||
161 | if (err) { | ||
162 | dev_dbg(sdmmc_dev(host), | ||
163 | "rtsx_usb_send_cmd failed (err = %d)\n", err); | ||
164 | return err; | ||
165 | } | ||
166 | |||
167 | err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); | ||
168 | if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { | ||
169 | sd_print_debug_regs(host); | ||
170 | |||
171 | if (!err) { | ||
172 | dev_dbg(sdmmc_dev(host), | ||
173 | "Transfer failed (SD_TRANSFER = %02x)\n", | ||
174 | ucr->rsp_buf[0]); | ||
175 | err = -EIO; | ||
176 | } else { | ||
177 | dev_dbg(sdmmc_dev(host), | ||
178 | "rtsx_usb_get_rsp failed (err = %d)\n", err); | ||
179 | } | ||
180 | |||
181 | return err; | ||
182 | } | ||
183 | |||
184 | if (cmd != NULL) { | ||
185 | cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); | ||
186 | dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", | ||
187 | cmd->resp[0]); | ||
188 | } | ||
189 | |||
190 | if (buf && buf_len) { | ||
191 | /* 2-byte aligned part */ | ||
192 | err = rtsx_usb_read_ppbuf(ucr, buf, byte_cnt - (byte_cnt % 2)); | ||
193 | if (err) { | ||
194 | dev_dbg(sdmmc_dev(host), | ||
195 | "rtsx_usb_read_ppbuf failed (err = %d)\n", err); | ||
196 | return err; | ||
197 | } | ||
198 | |||
199 | /* unaligned byte */ | ||
200 | if (byte_cnt % 2) | ||
201 | return rtsx_usb_read_register(ucr, | ||
202 | PPBUF_BASE2 + byte_cnt, | ||
203 | buf + byte_cnt - 1); | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int sd_write_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, | ||
210 | u16 byte_cnt, u8 *buf, int buf_len, int timeout) | ||
211 | { | ||
212 | struct rtsx_ucr *ucr = host->ucr; | ||
213 | int err; | ||
214 | u8 trans_mode; | ||
215 | |||
216 | if (!buf) | ||
217 | buf_len = 0; | ||
218 | |||
219 | if (buf && buf_len) { | ||
220 | err = rtsx_usb_write_ppbuf(ucr, buf, buf_len); | ||
221 | if (err) { | ||
222 | dev_dbg(sdmmc_dev(host), | ||
223 | "rtsx_usb_write_ppbuf failed (err = %d)\n", | ||
224 | err); | ||
225 | return err; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | trans_mode = (cmd != NULL) ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; | ||
230 | rtsx_usb_init_cmd(ucr); | ||
231 | |||
232 | if (cmd != NULL) { | ||
233 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, | ||
234 | cmd->opcode); | ||
235 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
236 | SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); | ||
237 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
238 | SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); | ||
239 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
240 | SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); | ||
241 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
242 | SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); | ||
243 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
244 | SD_CMD4, 0xFF, (u8)cmd->arg); | ||
245 | } | ||
246 | |||
247 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); | ||
248 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, | ||
249 | 0xFF, (u8)(byte_cnt >> 8)); | ||
250 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); | ||
251 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); | ||
252 | |||
253 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
254 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
255 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); | ||
256 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
257 | CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); | ||
258 | |||
259 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | ||
260 | trans_mode | SD_TRANSFER_START); | ||
261 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, | ||
262 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
263 | |||
264 | if (cmd != NULL) { | ||
265 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); | ||
266 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); | ||
267 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); | ||
268 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); | ||
269 | } | ||
270 | |||
271 | err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); | ||
272 | if (err) { | ||
273 | dev_dbg(sdmmc_dev(host), | ||
274 | "rtsx_usb_send_cmd failed (err = %d)\n", err); | ||
275 | return err; | ||
276 | } | ||
277 | |||
278 | err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); | ||
279 | if (err) { | ||
280 | sd_print_debug_regs(host); | ||
281 | dev_dbg(sdmmc_dev(host), | ||
282 | "rtsx_usb_get_rsp failed (err = %d)\n", err); | ||
283 | return err; | ||
284 | } | ||
285 | |||
286 | if (cmd != NULL) { | ||
287 | cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); | ||
288 | dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", | ||
289 | cmd->resp[0]); | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host, | ||
296 | struct mmc_command *cmd) | ||
297 | { | ||
298 | struct rtsx_ucr *ucr = host->ucr; | ||
299 | u8 cmd_idx = (u8)cmd->opcode; | ||
300 | u32 arg = cmd->arg; | ||
301 | int err = 0; | ||
302 | int timeout = 100; | ||
303 | int i; | ||
304 | u8 *ptr; | ||
305 | int stat_idx = 0; | ||
306 | int len = 2; | ||
307 | u8 rsp_type; | ||
308 | |||
309 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | ||
310 | __func__, cmd_idx, arg); | ||
311 | |||
312 | /* Response type: | ||
313 | * R0 | ||
314 | * R1, R5, R6, R7 | ||
315 | * R1b | ||
316 | * R2 | ||
317 | * R3, R4 | ||
318 | */ | ||
319 | switch (mmc_resp_type(cmd)) { | ||
320 | case MMC_RSP_NONE: | ||
321 | rsp_type = SD_RSP_TYPE_R0; | ||
322 | break; | ||
323 | case MMC_RSP_R1: | ||
324 | rsp_type = SD_RSP_TYPE_R1; | ||
325 | break; | ||
326 | case MMC_RSP_R1 & ~MMC_RSP_CRC: | ||
327 | rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; | ||
328 | break; | ||
329 | case MMC_RSP_R1B: | ||
330 | rsp_type = SD_RSP_TYPE_R1b; | ||
331 | break; | ||
332 | case MMC_RSP_R2: | ||
333 | rsp_type = SD_RSP_TYPE_R2; | ||
334 | break; | ||
335 | case MMC_RSP_R3: | ||
336 | rsp_type = SD_RSP_TYPE_R3; | ||
337 | break; | ||
338 | default: | ||
339 | dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); | ||
340 | err = -EINVAL; | ||
341 | goto out; | ||
342 | } | ||
343 | |||
344 | if (rsp_type == SD_RSP_TYPE_R1b) | ||
345 | timeout = 3000; | ||
346 | |||
347 | if (cmd->opcode == SD_SWITCH_VOLTAGE) { | ||
348 | err = rtsx_usb_write_register(ucr, SD_BUS_STAT, | ||
349 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, | ||
350 | SD_CLK_TOGGLE_EN); | ||
351 | if (err) | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | rtsx_usb_init_cmd(ucr); | ||
356 | |||
357 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); | ||
358 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); | ||
359 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); | ||
360 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); | ||
361 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); | ||
362 | |||
363 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); | ||
364 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, | ||
365 | 0x01, PINGPONG_BUFFER); | ||
366 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, | ||
367 | 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); | ||
368 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, | ||
369 | SD_TRANSFER_END | SD_STAT_IDLE, | ||
370 | SD_TRANSFER_END | SD_STAT_IDLE); | ||
371 | |||
372 | if (rsp_type == SD_RSP_TYPE_R2) { | ||
373 | /* Read data from ping-pong buffer */ | ||
374 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) | ||
375 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); | ||
376 | stat_idx = 16; | ||
377 | } else if (rsp_type != SD_RSP_TYPE_R0) { | ||
378 | /* Read data from SD_CMDx registers */ | ||
379 | for (i = SD_CMD0; i <= SD_CMD4; i++) | ||
380 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); | ||
381 | stat_idx = 5; | ||
382 | } | ||
383 | len += stat_idx; | ||
384 | |||
385 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_STAT1, 0, 0); | ||
386 | |||
387 | err = rtsx_usb_send_cmd(ucr, MODE_CR, 100); | ||
388 | if (err) { | ||
389 | dev_dbg(sdmmc_dev(host), | ||
390 | "rtsx_usb_send_cmd error (err = %d)\n", err); | ||
391 | goto out; | ||
392 | } | ||
393 | |||
394 | err = rtsx_usb_get_rsp(ucr, len, timeout); | ||
395 | if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { | ||
396 | sd_print_debug_regs(host); | ||
397 | sd_clear_error(host); | ||
398 | |||
399 | if (!err) { | ||
400 | dev_dbg(sdmmc_dev(host), | ||
401 | "Transfer failed (SD_TRANSFER = %02x)\n", | ||
402 | ucr->rsp_buf[0]); | ||
403 | err = -EIO; | ||
404 | } else { | ||
405 | dev_dbg(sdmmc_dev(host), | ||
406 | "rtsx_usb_get_rsp failed (err = %d)\n", err); | ||
407 | } | ||
408 | |||
409 | goto out; | ||
410 | } | ||
411 | |||
412 | if (rsp_type == SD_RSP_TYPE_R0) { | ||
413 | err = 0; | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | /* Skip result of CHECK_REG_CMD */ | ||
418 | ptr = ucr->rsp_buf + 1; | ||
419 | |||
420 | /* Check (Start,Transmission) bit of Response */ | ||
421 | if ((ptr[0] & 0xC0) != 0) { | ||
422 | err = -EILSEQ; | ||
423 | dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); | ||
424 | goto out; | ||
425 | } | ||
426 | |||
427 | /* Check CRC7 */ | ||
428 | if (!(rsp_type & SD_NO_CHECK_CRC7)) { | ||
429 | if (ptr[stat_idx] & SD_CRC7_ERR) { | ||
430 | err = -EILSEQ; | ||
431 | dev_dbg(sdmmc_dev(host), "CRC7 error\n"); | ||
432 | goto out; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | if (rsp_type == SD_RSP_TYPE_R2) { | ||
437 | for (i = 0; i < 4; i++) { | ||
438 | cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); | ||
439 | dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", | ||
440 | i, cmd->resp[i]); | ||
441 | } | ||
442 | } else { | ||
443 | cmd->resp[0] = get_unaligned_be32(ptr + 1); | ||
444 | dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", | ||
445 | cmd->resp[0]); | ||
446 | } | ||
447 | |||
448 | out: | ||
449 | cmd->error = err; | ||
450 | } | ||
451 | |||
452 | static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq) | ||
453 | { | ||
454 | struct rtsx_ucr *ucr = host->ucr; | ||
455 | struct mmc_data *data = mrq->data; | ||
456 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; | ||
457 | u8 cfg2, trans_mode; | ||
458 | int err; | ||
459 | u8 flag; | ||
460 | size_t data_len = data->blksz * data->blocks; | ||
461 | unsigned int pipe; | ||
462 | |||
463 | if (read) { | ||
464 | dev_dbg(sdmmc_dev(host), "%s: read %zu bytes\n", | ||
465 | __func__, data_len); | ||
466 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
467 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; | ||
468 | trans_mode = SD_TM_AUTO_READ_3; | ||
469 | } else { | ||
470 | dev_dbg(sdmmc_dev(host), "%s: write %zu bytes\n", | ||
471 | __func__, data_len); | ||
472 | cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
473 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; | ||
474 | trans_mode = SD_TM_AUTO_WRITE_3; | ||
475 | } | ||
476 | |||
477 | rtsx_usb_init_cmd(ucr); | ||
478 | |||
479 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); | ||
480 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); | ||
481 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, | ||
482 | 0xFF, (u8)data->blocks); | ||
483 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, | ||
484 | 0xFF, (u8)(data->blocks >> 8)); | ||
485 | |||
486 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, | ||
487 | 0x01, RING_BUFFER); | ||
488 | |||
489 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3, | ||
490 | 0xFF, (u8)(data_len >> 24)); | ||
491 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2, | ||
492 | 0xFF, (u8)(data_len >> 16)); | ||
493 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1, | ||
494 | 0xFF, (u8)(data_len >> 8)); | ||
495 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, | ||
496 | 0xFF, (u8)data_len); | ||
497 | if (read) { | ||
498 | flag = MODE_CDIR; | ||
499 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, | ||
500 | 0x03 | DMA_PACK_SIZE_MASK, | ||
501 | DMA_DIR_FROM_CARD | DMA_EN | DMA_512); | ||
502 | } else { | ||
503 | flag = MODE_CDOR; | ||
504 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, | ||
505 | 0x03 | DMA_PACK_SIZE_MASK, | ||
506 | DMA_DIR_TO_CARD | DMA_EN | DMA_512); | ||
507 | } | ||
508 | |||
509 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); | ||
510 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | ||
511 | trans_mode | SD_TRANSFER_START); | ||
512 | rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, | ||
513 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
514 | |||
515 | err = rtsx_usb_send_cmd(ucr, flag, 100); | ||
516 | if (err) | ||
517 | return err; | ||
518 | |||
519 | if (read) | ||
520 | pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN); | ||
521 | else | ||
522 | pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT); | ||
523 | |||
524 | err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len, | ||
525 | data->sg_len, NULL, 10000); | ||
526 | if (err) { | ||
527 | dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n" | ||
528 | , err); | ||
529 | sd_clear_error(host); | ||
530 | return err; | ||
531 | } | ||
532 | |||
533 | return rtsx_usb_get_rsp(ucr, 1, 2000); | ||
534 | } | ||
535 | |||
536 | static inline void sd_enable_initial_mode(struct rtsx_usb_sdmmc *host) | ||
537 | { | ||
538 | rtsx_usb_write_register(host->ucr, SD_CFG1, | ||
539 | SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); | ||
540 | } | ||
541 | |||
542 | static inline void sd_disable_initial_mode(struct rtsx_usb_sdmmc *host) | ||
543 | { | ||
544 | rtsx_usb_write_register(host->ucr, SD_CFG1, | ||
545 | SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); | ||
546 | } | ||
547 | |||
548 | static void sd_normal_rw(struct rtsx_usb_sdmmc *host, | ||
549 | struct mmc_request *mrq) | ||
550 | { | ||
551 | struct mmc_command *cmd = mrq->cmd; | ||
552 | struct mmc_data *data = mrq->data; | ||
553 | u8 *buf; | ||
554 | |||
555 | buf = kzalloc(data->blksz, GFP_NOIO); | ||
556 | if (!buf) { | ||
557 | cmd->error = -ENOMEM; | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | if (data->flags & MMC_DATA_READ) { | ||
562 | if (host->initial_mode) | ||
563 | sd_disable_initial_mode(host); | ||
564 | |||
565 | cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, | ||
566 | data->blksz, 200); | ||
567 | |||
568 | if (host->initial_mode) | ||
569 | sd_enable_initial_mode(host); | ||
570 | |||
571 | sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); | ||
572 | } else { | ||
573 | sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); | ||
574 | |||
575 | cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, | ||
576 | data->blksz, 200); | ||
577 | } | ||
578 | |||
579 | kfree(buf); | ||
580 | } | ||
581 | |||
582 | static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) | ||
583 | { | ||
584 | struct rtsx_ucr *ucr = host->ucr; | ||
585 | int err; | ||
586 | |||
587 | dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n", | ||
588 | __func__, tx ? "TX" : "RX", sample_point); | ||
589 | |||
590 | rtsx_usb_init_cmd(ucr); | ||
591 | |||
592 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); | ||
593 | |||
594 | if (tx) | ||
595 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, | ||
596 | 0x0F, sample_point); | ||
597 | else | ||
598 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK1_CTL, | ||
599 | 0x0F, sample_point); | ||
600 | |||
601 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); | ||
602 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, | ||
603 | PHASE_NOT_RESET, PHASE_NOT_RESET); | ||
604 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); | ||
605 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0); | ||
606 | |||
607 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
608 | if (err) | ||
609 | return err; | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static inline u32 get_phase_point(u32 phase_map, unsigned int idx) | ||
615 | { | ||
616 | idx &= MAX_PHASE; | ||
617 | return phase_map & (1 << idx); | ||
618 | } | ||
619 | |||
620 | static int get_phase_len(u32 phase_map, unsigned int idx) | ||
621 | { | ||
622 | int i; | ||
623 | |||
624 | for (i = 0; i < MAX_PHASE + 1; i++) { | ||
625 | if (get_phase_point(phase_map, idx + i) == 0) | ||
626 | return i; | ||
627 | } | ||
628 | return MAX_PHASE + 1; | ||
629 | } | ||
630 | |||
631 | static u8 sd_search_final_phase(struct rtsx_usb_sdmmc *host, u32 phase_map) | ||
632 | { | ||
633 | int start = 0, len = 0; | ||
634 | int start_final = 0, len_final = 0; | ||
635 | u8 final_phase = 0xFF; | ||
636 | |||
637 | if (phase_map == 0) { | ||
638 | dev_dbg(sdmmc_dev(host), "Phase: [map:%x]\n", phase_map); | ||
639 | return final_phase; | ||
640 | } | ||
641 | |||
642 | while (start < MAX_PHASE + 1) { | ||
643 | len = get_phase_len(phase_map, start); | ||
644 | if (len_final < len) { | ||
645 | start_final = start; | ||
646 | len_final = len; | ||
647 | } | ||
648 | start += len ? len : 1; | ||
649 | } | ||
650 | |||
651 | final_phase = (start_final + len_final / 2) & MAX_PHASE; | ||
652 | dev_dbg(sdmmc_dev(host), "Phase: [map:%x] [maxlen:%d] [final:%d]\n", | ||
653 | phase_map, len_final, final_phase); | ||
654 | |||
655 | return final_phase; | ||
656 | } | ||
657 | |||
658 | static void sd_wait_data_idle(struct rtsx_usb_sdmmc *host) | ||
659 | { | ||
660 | int err, i; | ||
661 | u8 val = 0; | ||
662 | |||
663 | for (i = 0; i < 100; i++) { | ||
664 | err = rtsx_usb_ep0_read_register(host->ucr, | ||
665 | SD_DATA_STATE, &val); | ||
666 | if (val & SD_DATA_IDLE) | ||
667 | return; | ||
668 | |||
669 | usleep_range(100, 1000); | ||
670 | } | ||
671 | } | ||
672 | |||
673 | static int sd_tuning_rx_cmd(struct rtsx_usb_sdmmc *host, | ||
674 | u8 opcode, u8 sample_point) | ||
675 | { | ||
676 | int err; | ||
677 | struct mmc_command cmd = {0}; | ||
678 | |||
679 | err = sd_change_phase(host, sample_point, 0); | ||
680 | if (err) | ||
681 | return err; | ||
682 | |||
683 | cmd.opcode = MMC_SEND_TUNING_BLOCK; | ||
684 | err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); | ||
685 | if (err) { | ||
686 | /* Wait till SD DATA IDLE */ | ||
687 | sd_wait_data_idle(host); | ||
688 | sd_clear_error(host); | ||
689 | return err; | ||
690 | } | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static void sd_tuning_phase(struct rtsx_usb_sdmmc *host, | ||
696 | u8 opcode, u16 *phase_map) | ||
697 | { | ||
698 | int err, i; | ||
699 | u16 raw_phase_map = 0; | ||
700 | |||
701 | for (i = MAX_PHASE; i >= 0; i--) { | ||
702 | err = sd_tuning_rx_cmd(host, opcode, (u8)i); | ||
703 | if (!err) | ||
704 | raw_phase_map |= 1 << i; | ||
705 | } | ||
706 | |||
707 | if (phase_map) | ||
708 | *phase_map = raw_phase_map; | ||
709 | } | ||
710 | |||
711 | static int sd_tuning_rx(struct rtsx_usb_sdmmc *host, u8 opcode) | ||
712 | { | ||
713 | int err, i; | ||
714 | u16 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; | ||
715 | u8 final_phase; | ||
716 | |||
717 | /* setting fixed default TX phase */ | ||
718 | err = sd_change_phase(host, 0x01, 1); | ||
719 | if (err) { | ||
720 | dev_dbg(sdmmc_dev(host), "TX phase setting failed\n"); | ||
721 | return err; | ||
722 | } | ||
723 | |||
724 | /* tuning RX phase */ | ||
725 | for (i = 0; i < RX_TUNING_CNT; i++) { | ||
726 | sd_tuning_phase(host, opcode, &(raw_phase_map[i])); | ||
727 | |||
728 | if (raw_phase_map[i] == 0) | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | phase_map = 0xFFFF; | ||
733 | for (i = 0; i < RX_TUNING_CNT; i++) { | ||
734 | dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%04x\n", | ||
735 | i, raw_phase_map[i]); | ||
736 | phase_map &= raw_phase_map[i]; | ||
737 | } | ||
738 | dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%04x\n", phase_map); | ||
739 | |||
740 | if (phase_map) { | ||
741 | final_phase = sd_search_final_phase(host, phase_map); | ||
742 | if (final_phase == 0xFF) | ||
743 | return -EINVAL; | ||
744 | |||
745 | err = sd_change_phase(host, final_phase, 0); | ||
746 | if (err) | ||
747 | return err; | ||
748 | } else { | ||
749 | return -EINVAL; | ||
750 | } | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int sdmmc_get_ro(struct mmc_host *mmc) | ||
756 | { | ||
757 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
758 | struct rtsx_ucr *ucr = host->ucr; | ||
759 | int err; | ||
760 | u16 val; | ||
761 | |||
762 | if (host->host_removal) | ||
763 | return -ENOMEDIUM; | ||
764 | |||
765 | mutex_lock(&ucr->dev_mutex); | ||
766 | |||
767 | /* Check SD card detect */ | ||
768 | err = rtsx_usb_get_card_status(ucr, &val); | ||
769 | |||
770 | mutex_unlock(&ucr->dev_mutex); | ||
771 | |||
772 | |||
773 | /* Treat failed detection as non-ro */ | ||
774 | if (err) | ||
775 | return 0; | ||
776 | |||
777 | if (val & SD_WP) | ||
778 | return 1; | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int sdmmc_get_cd(struct mmc_host *mmc) | ||
784 | { | ||
785 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
786 | struct rtsx_ucr *ucr = host->ucr; | ||
787 | int err; | ||
788 | u16 val; | ||
789 | |||
790 | if (host->host_removal) | ||
791 | return -ENOMEDIUM; | ||
792 | |||
793 | mutex_lock(&ucr->dev_mutex); | ||
794 | |||
795 | /* Check SD card detect */ | ||
796 | err = rtsx_usb_get_card_status(ucr, &val); | ||
797 | |||
798 | mutex_unlock(&ucr->dev_mutex); | ||
799 | |||
800 | /* Treat failed detection as non-exist */ | ||
801 | if (err) | ||
802 | goto no_card; | ||
803 | |||
804 | if (val & SD_CD) { | ||
805 | host->card_exist = true; | ||
806 | return 1; | ||
807 | } | ||
808 | |||
809 | no_card: | ||
810 | host->card_exist = false; | ||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
815 | { | ||
816 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
817 | struct rtsx_ucr *ucr = host->ucr; | ||
818 | struct mmc_command *cmd = mrq->cmd; | ||
819 | struct mmc_data *data = mrq->data; | ||
820 | unsigned int data_size = 0; | ||
821 | |||
822 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | ||
823 | |||
824 | if (host->host_removal) { | ||
825 | cmd->error = -ENOMEDIUM; | ||
826 | goto finish; | ||
827 | } | ||
828 | |||
829 | if ((!host->card_exist)) { | ||
830 | cmd->error = -ENOMEDIUM; | ||
831 | goto finish_detect_card; | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * Reject SDIO CMDs to speed up card identification | ||
836 | * since unsupported | ||
837 | */ | ||
838 | if (cmd->opcode == SD_IO_SEND_OP_COND || | ||
839 | cmd->opcode == SD_IO_RW_DIRECT || | ||
840 | cmd->opcode == SD_IO_RW_EXTENDED) { | ||
841 | cmd->error = -EINVAL; | ||
842 | goto finish; | ||
843 | } | ||
844 | |||
845 | mutex_lock(&ucr->dev_mutex); | ||
846 | |||
847 | mutex_lock(&host->host_mutex); | ||
848 | host->mrq = mrq; | ||
849 | mutex_unlock(&host->host_mutex); | ||
850 | |||
851 | if (mrq->data) | ||
852 | data_size = data->blocks * data->blksz; | ||
853 | |||
854 | if (!data_size) { | ||
855 | sd_send_cmd_get_rsp(host, cmd); | ||
856 | } else if ((!(data_size % 512) && cmd->opcode != MMC_SEND_EXT_CSD) || | ||
857 | mmc_op_multi(cmd->opcode)) { | ||
858 | sd_send_cmd_get_rsp(host, cmd); | ||
859 | |||
860 | if (!cmd->error) { | ||
861 | sd_rw_multi(host, mrq); | ||
862 | |||
863 | if (mmc_op_multi(cmd->opcode) && mrq->stop) { | ||
864 | sd_send_cmd_get_rsp(host, mrq->stop); | ||
865 | rtsx_usb_write_register(ucr, MC_FIFO_CTL, | ||
866 | FIFO_FLUSH, FIFO_FLUSH); | ||
867 | } | ||
868 | } | ||
869 | } else { | ||
870 | sd_normal_rw(host, mrq); | ||
871 | } | ||
872 | |||
873 | if (mrq->data) { | ||
874 | if (cmd->error || data->error) | ||
875 | data->bytes_xfered = 0; | ||
876 | else | ||
877 | data->bytes_xfered = data->blocks * data->blksz; | ||
878 | } | ||
879 | |||
880 | mutex_unlock(&ucr->dev_mutex); | ||
881 | |||
882 | finish_detect_card: | ||
883 | if (cmd->error) { | ||
884 | /* | ||
885 | * detect card when fail to update card existence state and | ||
886 | * speed up card removal when retry | ||
887 | */ | ||
888 | sdmmc_get_cd(mmc); | ||
889 | dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); | ||
890 | } | ||
891 | |||
892 | finish: | ||
893 | mutex_lock(&host->host_mutex); | ||
894 | host->mrq = NULL; | ||
895 | mutex_unlock(&host->host_mutex); | ||
896 | |||
897 | mmc_request_done(mmc, mrq); | ||
898 | } | ||
899 | |||
900 | static int sd_set_bus_width(struct rtsx_usb_sdmmc *host, | ||
901 | unsigned char bus_width) | ||
902 | { | ||
903 | int err = 0; | ||
904 | u8 width[] = { | ||
905 | [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, | ||
906 | [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, | ||
907 | [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, | ||
908 | }; | ||
909 | |||
910 | if (bus_width <= MMC_BUS_WIDTH_8) | ||
911 | err = rtsx_usb_write_register(host->ucr, SD_CFG1, | ||
912 | 0x03, width[bus_width]); | ||
913 | |||
914 | return err; | ||
915 | } | ||
916 | |||
917 | static int sd_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr) | ||
918 | { | ||
919 | rtsx_usb_init_cmd(ucr); | ||
920 | |||
921 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); | ||
922 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
923 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
924 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
925 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); | ||
926 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); | ||
927 | |||
928 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
929 | } | ||
930 | |||
931 | static int sd_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr) | ||
932 | { | ||
933 | rtsx_usb_init_cmd(ucr); | ||
934 | |||
935 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); | ||
936 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); | ||
937 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); | ||
938 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
939 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); | ||
940 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); | ||
941 | |||
942 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
943 | } | ||
944 | |||
945 | static int sd_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr) | ||
946 | { | ||
947 | rtsx_usb_init_cmd(ucr); | ||
948 | |||
949 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); | ||
950 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); | ||
951 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9); | ||
952 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); | ||
953 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); | ||
954 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); | ||
955 | |||
956 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
957 | } | ||
958 | |||
959 | static int sd_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr) | ||
960 | { | ||
961 | rtsx_usb_init_cmd(ucr); | ||
962 | |||
963 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); | ||
964 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A); | ||
965 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5); | ||
966 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A); | ||
967 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65); | ||
968 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A); | ||
969 | |||
970 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
971 | } | ||
972 | |||
973 | static int sd_power_on(struct rtsx_usb_sdmmc *host) | ||
974 | { | ||
975 | struct rtsx_ucr *ucr = host->ucr; | ||
976 | int err; | ||
977 | |||
978 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | ||
979 | rtsx_usb_init_cmd(ucr); | ||
980 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); | ||
981 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE, | ||
982 | CARD_SHARE_MASK, CARD_SHARE_SD); | ||
983 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, | ||
984 | SD_CLK_EN, SD_CLK_EN); | ||
985 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
986 | if (err) | ||
987 | return err; | ||
988 | |||
989 | if (CHECK_PKG(ucr, LQFP48)) | ||
990 | err = sd_pull_ctl_enable_lqfp48(ucr); | ||
991 | else | ||
992 | err = sd_pull_ctl_enable_qfn24(ucr); | ||
993 | if (err) | ||
994 | return err; | ||
995 | |||
996 | err = rtsx_usb_write_register(ucr, CARD_PWR_CTL, | ||
997 | POWER_MASK, PARTIAL_POWER_ON); | ||
998 | if (err) | ||
999 | return err; | ||
1000 | |||
1001 | usleep_range(800, 1000); | ||
1002 | |||
1003 | rtsx_usb_init_cmd(ucr); | ||
1004 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
1005 | POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON); | ||
1006 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, | ||
1007 | SD_OUTPUT_EN, SD_OUTPUT_EN); | ||
1008 | |||
1009 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
1010 | } | ||
1011 | |||
1012 | static int sd_power_off(struct rtsx_usb_sdmmc *host) | ||
1013 | { | ||
1014 | struct rtsx_ucr *ucr = host->ucr; | ||
1015 | int err; | ||
1016 | |||
1017 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | ||
1018 | rtsx_usb_init_cmd(ucr); | ||
1019 | |||
1020 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); | ||
1021 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); | ||
1022 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
1023 | POWER_MASK, POWER_OFF); | ||
1024 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
1025 | POWER_MASK|LDO3318_PWR_MASK, POWER_OFF|LDO_SUSPEND); | ||
1026 | |||
1027 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
1028 | if (err) | ||
1029 | return err; | ||
1030 | |||
1031 | if (CHECK_PKG(ucr, LQFP48)) | ||
1032 | return sd_pull_ctl_disable_lqfp48(ucr); | ||
1033 | return sd_pull_ctl_disable_qfn24(ucr); | ||
1034 | } | ||
1035 | |||
1036 | static int sd_set_power_mode(struct rtsx_usb_sdmmc *host, | ||
1037 | unsigned char power_mode) | ||
1038 | { | ||
1039 | int err; | ||
1040 | |||
1041 | if (power_mode != MMC_POWER_OFF) | ||
1042 | power_mode = MMC_POWER_ON; | ||
1043 | |||
1044 | if (power_mode == host->power_mode) | ||
1045 | return 0; | ||
1046 | |||
1047 | if (power_mode == MMC_POWER_OFF) { | ||
1048 | err = sd_power_off(host); | ||
1049 | pm_runtime_put(sdmmc_dev(host)); | ||
1050 | } else { | ||
1051 | pm_runtime_get_sync(sdmmc_dev(host)); | ||
1052 | err = sd_power_on(host); | ||
1053 | } | ||
1054 | |||
1055 | if (!err) | ||
1056 | host->power_mode = power_mode; | ||
1057 | |||
1058 | return err; | ||
1059 | } | ||
1060 | |||
1061 | static int sd_set_timing(struct rtsx_usb_sdmmc *host, | ||
1062 | unsigned char timing, bool *ddr_mode) | ||
1063 | { | ||
1064 | struct rtsx_ucr *ucr = host->ucr; | ||
1065 | int err; | ||
1066 | |||
1067 | *ddr_mode = false; | ||
1068 | |||
1069 | rtsx_usb_init_cmd(ucr); | ||
1070 | |||
1071 | switch (timing) { | ||
1072 | case MMC_TIMING_UHS_SDR104: | ||
1073 | case MMC_TIMING_UHS_SDR50: | ||
1074 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, | ||
1075 | 0x0C | SD_ASYNC_FIFO_RST, | ||
1076 | SD_30_MODE | SD_ASYNC_FIFO_RST); | ||
1077 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, | ||
1078 | CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); | ||
1079 | break; | ||
1080 | |||
1081 | case MMC_TIMING_UHS_DDR50: | ||
1082 | *ddr_mode = true; | ||
1083 | |||
1084 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, | ||
1085 | 0x0C | SD_ASYNC_FIFO_RST, | ||
1086 | SD_DDR_MODE | SD_ASYNC_FIFO_RST); | ||
1087 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, | ||
1088 | CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); | ||
1089 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, | ||
1090 | DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); | ||
1091 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, | ||
1092 | DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, | ||
1093 | DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); | ||
1094 | break; | ||
1095 | |||
1096 | case MMC_TIMING_MMC_HS: | ||
1097 | case MMC_TIMING_SD_HS: | ||
1098 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, | ||
1099 | 0x0C, SD_20_MODE); | ||
1100 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, | ||
1101 | CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); | ||
1102 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, | ||
1103 | SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); | ||
1104 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, | ||
1105 | SD20_RX_SEL_MASK, SD20_RX_14_DELAY); | ||
1106 | break; | ||
1107 | |||
1108 | default: | ||
1109 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
1110 | SD_CFG1, 0x0C, SD_20_MODE); | ||
1111 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, | ||
1112 | CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); | ||
1113 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | ||
1114 | SD_PUSH_POINT_CTL, 0xFF, 0); | ||
1115 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, | ||
1116 | SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); | ||
1117 | break; | ||
1118 | } | ||
1119 | |||
1120 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
1121 | |||
1122 | return err; | ||
1123 | } | ||
1124 | |||
1125 | static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
1126 | { | ||
1127 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
1128 | struct rtsx_ucr *ucr = host->ucr; | ||
1129 | |||
1130 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | ||
1131 | mutex_lock(&ucr->dev_mutex); | ||
1132 | |||
1133 | if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { | ||
1134 | mutex_unlock(&ucr->dev_mutex); | ||
1135 | return; | ||
1136 | } | ||
1137 | |||
1138 | sd_set_power_mode(host, ios->power_mode); | ||
1139 | sd_set_bus_width(host, ios->bus_width); | ||
1140 | sd_set_timing(host, ios->timing, &host->ddr_mode); | ||
1141 | |||
1142 | host->vpclk = false; | ||
1143 | host->double_clk = true; | ||
1144 | |||
1145 | switch (ios->timing) { | ||
1146 | case MMC_TIMING_UHS_SDR104: | ||
1147 | case MMC_TIMING_UHS_SDR50: | ||
1148 | host->ssc_depth = SSC_DEPTH_2M; | ||
1149 | host->vpclk = true; | ||
1150 | host->double_clk = false; | ||
1151 | break; | ||
1152 | case MMC_TIMING_UHS_DDR50: | ||
1153 | case MMC_TIMING_UHS_SDR25: | ||
1154 | host->ssc_depth = SSC_DEPTH_1M; | ||
1155 | break; | ||
1156 | default: | ||
1157 | host->ssc_depth = SSC_DEPTH_512K; | ||
1158 | break; | ||
1159 | } | ||
1160 | |||
1161 | host->initial_mode = (ios->clock <= 1000000) ? true : false; | ||
1162 | host->clock = ios->clock; | ||
1163 | |||
1164 | rtsx_usb_switch_clock(host->ucr, host->clock, host->ssc_depth, | ||
1165 | host->initial_mode, host->double_clk, host->vpclk); | ||
1166 | |||
1167 | mutex_unlock(&ucr->dev_mutex); | ||
1168 | dev_dbg(sdmmc_dev(host), "%s end\n", __func__); | ||
1169 | } | ||
1170 | |||
1171 | static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | ||
1172 | { | ||
1173 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
1174 | struct rtsx_ucr *ucr = host->ucr; | ||
1175 | int err = 0; | ||
1176 | |||
1177 | dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", | ||
1178 | __func__, ios->signal_voltage); | ||
1179 | |||
1180 | if (host->host_removal) | ||
1181 | return -ENOMEDIUM; | ||
1182 | |||
1183 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) | ||
1184 | return -EPERM; | ||
1185 | |||
1186 | mutex_lock(&ucr->dev_mutex); | ||
1187 | |||
1188 | err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD); | ||
1189 | if (err) { | ||
1190 | mutex_unlock(&ucr->dev_mutex); | ||
1191 | return err; | ||
1192 | } | ||
1193 | |||
1194 | /* Let mmc core do the busy checking, simply stop the forced-toggle | ||
1195 | * clock(while issuing CMD11) and switch voltage. | ||
1196 | */ | ||
1197 | rtsx_usb_init_cmd(ucr); | ||
1198 | |||
1199 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { | ||
1200 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, | ||
1201 | SD_IO_USING_1V8, SD_IO_USING_3V3); | ||
1202 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, | ||
1203 | TUNE_SD18_MASK, TUNE_SD18_3V3); | ||
1204 | } else { | ||
1205 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BUS_STAT, | ||
1206 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, | ||
1207 | SD_CLK_FORCE_STOP); | ||
1208 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, | ||
1209 | SD_IO_USING_1V8, SD_IO_USING_1V8); | ||
1210 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, | ||
1211 | TUNE_SD18_MASK, TUNE_SD18_1V8); | ||
1212 | } | ||
1213 | |||
1214 | err = rtsx_usb_send_cmd(ucr, MODE_C, 100); | ||
1215 | mutex_unlock(&ucr->dev_mutex); | ||
1216 | |||
1217 | return err; | ||
1218 | } | ||
1219 | |||
1220 | static int sdmmc_card_busy(struct mmc_host *mmc) | ||
1221 | { | ||
1222 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
1223 | struct rtsx_ucr *ucr = host->ucr; | ||
1224 | int err; | ||
1225 | u8 stat; | ||
1226 | u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS | ||
1227 | | SD_DAT0_STATUS; | ||
1228 | |||
1229 | dev_dbg(sdmmc_dev(host), "%s\n", __func__); | ||
1230 | |||
1231 | mutex_lock(&ucr->dev_mutex); | ||
1232 | |||
1233 | err = rtsx_usb_write_register(ucr, SD_BUS_STAT, | ||
1234 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, | ||
1235 | SD_CLK_TOGGLE_EN); | ||
1236 | if (err) | ||
1237 | goto out; | ||
1238 | |||
1239 | mdelay(1); | ||
1240 | |||
1241 | err = rtsx_usb_read_register(ucr, SD_BUS_STAT, &stat); | ||
1242 | if (err) | ||
1243 | goto out; | ||
1244 | |||
1245 | err = rtsx_usb_write_register(ucr, SD_BUS_STAT, | ||
1246 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); | ||
1247 | out: | ||
1248 | mutex_unlock(&ucr->dev_mutex); | ||
1249 | |||
1250 | if (err) | ||
1251 | return err; | ||
1252 | |||
1253 | /* check if any pin between dat[0:3] is low */ | ||
1254 | if ((stat & mask) != mask) | ||
1255 | return 1; | ||
1256 | else | ||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | ||
1261 | { | ||
1262 | struct rtsx_usb_sdmmc *host = mmc_priv(mmc); | ||
1263 | struct rtsx_ucr *ucr = host->ucr; | ||
1264 | int err = 0; | ||
1265 | |||
1266 | if (host->host_removal) | ||
1267 | return -ENOMEDIUM; | ||
1268 | |||
1269 | mutex_lock(&ucr->dev_mutex); | ||
1270 | |||
1271 | if (!host->ddr_mode) | ||
1272 | err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); | ||
1273 | |||
1274 | mutex_unlock(&ucr->dev_mutex); | ||
1275 | |||
1276 | return err; | ||
1277 | } | ||
1278 | |||
1279 | static const struct mmc_host_ops rtsx_usb_sdmmc_ops = { | ||
1280 | .request = sdmmc_request, | ||
1281 | .set_ios = sdmmc_set_ios, | ||
1282 | .get_ro = sdmmc_get_ro, | ||
1283 | .get_cd = sdmmc_get_cd, | ||
1284 | .start_signal_voltage_switch = sdmmc_switch_voltage, | ||
1285 | .card_busy = sdmmc_card_busy, | ||
1286 | .execute_tuning = sdmmc_execute_tuning, | ||
1287 | }; | ||
1288 | |||
1289 | #ifdef RTSX_USB_USE_LEDS_CLASS | ||
1290 | static void rtsx_usb_led_control(struct led_classdev *led, | ||
1291 | enum led_brightness brightness) | ||
1292 | { | ||
1293 | struct rtsx_usb_sdmmc *host = container_of(led, | ||
1294 | struct rtsx_usb_sdmmc, led); | ||
1295 | |||
1296 | if (host->host_removal) | ||
1297 | return; | ||
1298 | |||
1299 | host->led.brightness = brightness; | ||
1300 | schedule_work(&host->led_work); | ||
1301 | } | ||
1302 | |||
1303 | static void rtsx_usb_update_led(struct work_struct *work) | ||
1304 | { | ||
1305 | struct rtsx_usb_sdmmc *host = | ||
1306 | container_of(work, struct rtsx_usb_sdmmc, led_work); | ||
1307 | struct rtsx_ucr *ucr = host->ucr; | ||
1308 | |||
1309 | mutex_lock(&ucr->dev_mutex); | ||
1310 | |||
1311 | if (host->led.brightness == LED_OFF) | ||
1312 | rtsx_usb_turn_off_led(ucr); | ||
1313 | else | ||
1314 | rtsx_usb_turn_on_led(ucr); | ||
1315 | |||
1316 | mutex_unlock(&ucr->dev_mutex); | ||
1317 | } | ||
1318 | #endif | ||
1319 | |||
1320 | static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) | ||
1321 | { | ||
1322 | struct mmc_host *mmc = host->mmc; | ||
1323 | |||
1324 | mmc->f_min = 250000; | ||
1325 | mmc->f_max = 208000000; | ||
1326 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; | ||
1327 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | | ||
1328 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | | ||
1329 | MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | | ||
1330 | MMC_CAP_NEEDS_POLL; | ||
1331 | |||
1332 | mmc->max_current_330 = 400; | ||
1333 | mmc->max_current_180 = 800; | ||
1334 | mmc->ops = &rtsx_usb_sdmmc_ops; | ||
1335 | mmc->max_segs = 256; | ||
1336 | mmc->max_seg_size = 65536; | ||
1337 | mmc->max_blk_size = 512; | ||
1338 | mmc->max_blk_count = 65535; | ||
1339 | mmc->max_req_size = 524288; | ||
1340 | |||
1341 | host->power_mode = MMC_POWER_OFF; | ||
1342 | } | ||
1343 | |||
1344 | static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) | ||
1345 | { | ||
1346 | struct mmc_host *mmc; | ||
1347 | struct rtsx_usb_sdmmc *host; | ||
1348 | struct rtsx_ucr *ucr; | ||
1349 | #ifdef RTSX_USB_USE_LEDS_CLASS | ||
1350 | int err; | ||
1351 | #endif | ||
1352 | |||
1353 | ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); | ||
1354 | if (!ucr) | ||
1355 | return -ENXIO; | ||
1356 | |||
1357 | dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n"); | ||
1358 | |||
1359 | mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); | ||
1360 | if (!mmc) | ||
1361 | return -ENOMEM; | ||
1362 | |||
1363 | host = mmc_priv(mmc); | ||
1364 | host->ucr = ucr; | ||
1365 | host->mmc = mmc; | ||
1366 | host->pdev = pdev; | ||
1367 | platform_set_drvdata(pdev, host); | ||
1368 | |||
1369 | mutex_init(&host->host_mutex); | ||
1370 | rtsx_usb_init_host(host); | ||
1371 | pm_runtime_enable(&pdev->dev); | ||
1372 | |||
1373 | #ifdef RTSX_USB_USE_LEDS_CLASS | ||
1374 | snprintf(host->led_name, sizeof(host->led_name), | ||
1375 | "%s::", mmc_hostname(mmc)); | ||
1376 | host->led.name = host->led_name; | ||
1377 | host->led.brightness = LED_OFF; | ||
1378 | host->led.default_trigger = mmc_hostname(mmc); | ||
1379 | host->led.brightness_set = rtsx_usb_led_control; | ||
1380 | |||
1381 | err = led_classdev_register(mmc_dev(mmc), &host->led); | ||
1382 | if (err) | ||
1383 | dev_err(&(pdev->dev), | ||
1384 | "Failed to register LED device: %d\n", err); | ||
1385 | INIT_WORK(&host->led_work, rtsx_usb_update_led); | ||
1386 | |||
1387 | #endif | ||
1388 | mmc_add_host(mmc); | ||
1389 | |||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) | ||
1394 | { | ||
1395 | struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); | ||
1396 | struct mmc_host *mmc; | ||
1397 | |||
1398 | if (!host) | ||
1399 | return 0; | ||
1400 | |||
1401 | mmc = host->mmc; | ||
1402 | host->host_removal = true; | ||
1403 | |||
1404 | mutex_lock(&host->host_mutex); | ||
1405 | if (host->mrq) { | ||
1406 | dev_dbg(&(pdev->dev), | ||
1407 | "%s: Controller removed during transfer\n", | ||
1408 | mmc_hostname(mmc)); | ||
1409 | host->mrq->cmd->error = -ENOMEDIUM; | ||
1410 | if (host->mrq->stop) | ||
1411 | host->mrq->stop->error = -ENOMEDIUM; | ||
1412 | mmc_request_done(mmc, host->mrq); | ||
1413 | } | ||
1414 | mutex_unlock(&host->host_mutex); | ||
1415 | |||
1416 | mmc_remove_host(mmc); | ||
1417 | |||
1418 | #ifdef RTSX_USB_USE_LEDS_CLASS | ||
1419 | cancel_work_sync(&host->led_work); | ||
1420 | led_classdev_unregister(&host->led); | ||
1421 | #endif | ||
1422 | |||
1423 | mmc_free_host(mmc); | ||
1424 | pm_runtime_disable(&pdev->dev); | ||
1425 | platform_set_drvdata(pdev, NULL); | ||
1426 | |||
1427 | dev_dbg(&(pdev->dev), | ||
1428 | ": Realtek USB SD/MMC module has been removed\n"); | ||
1429 | |||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | static struct platform_device_id rtsx_usb_sdmmc_ids[] = { | ||
1434 | { | ||
1435 | .name = "rtsx_usb_sdmmc", | ||
1436 | }, { | ||
1437 | /* sentinel */ | ||
1438 | } | ||
1439 | }; | ||
1440 | MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); | ||
1441 | |||
1442 | static struct platform_driver rtsx_usb_sdmmc_driver = { | ||
1443 | .probe = rtsx_usb_sdmmc_drv_probe, | ||
1444 | .remove = rtsx_usb_sdmmc_drv_remove, | ||
1445 | .id_table = rtsx_usb_sdmmc_ids, | ||
1446 | .driver = { | ||
1447 | .owner = THIS_MODULE, | ||
1448 | .name = "rtsx_usb_sdmmc", | ||
1449 | }, | ||
1450 | }; | ||
1451 | module_platform_driver(rtsx_usb_sdmmc_driver); | ||
1452 | |||
1453 | MODULE_LICENSE("GPL v2"); | ||
1454 | MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>"); | ||
1455 | MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver"); | ||
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index 8fc9d6df87f6..1685f63b9e5d 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c | |||
@@ -28,17 +28,6 @@ | |||
28 | 28 | ||
29 | #include <linux/mfd/tps65090.h> | 29 | #include <linux/mfd/tps65090.h> |
30 | 30 | ||
31 | #define TPS65090_REG_INTR_STS 0x00 | ||
32 | #define TPS65090_REG_INTR_MASK 0x02 | ||
33 | #define TPS65090_REG_CG_CTRL0 0x04 | ||
34 | #define TPS65090_REG_CG_CTRL1 0x05 | ||
35 | #define TPS65090_REG_CG_CTRL2 0x06 | ||
36 | #define TPS65090_REG_CG_CTRL3 0x07 | ||
37 | #define TPS65090_REG_CG_CTRL4 0x08 | ||
38 | #define TPS65090_REG_CG_CTRL5 0x09 | ||
39 | #define TPS65090_REG_CG_STATUS1 0x0a | ||
40 | #define TPS65090_REG_CG_STATUS2 0x0b | ||
41 | |||
42 | #define TPS65090_CHARGER_ENABLE BIT(0) | 31 | #define TPS65090_CHARGER_ENABLE BIT(0) |
43 | #define TPS65090_VACG BIT(1) | 32 | #define TPS65090_VACG BIT(1) |
44 | #define TPS65090_NOITERM BIT(5) | 33 | #define TPS65090_NOITERM BIT(5) |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 903eb37f047a..f0cc9e6dac3a 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -266,11 +266,12 @@ config REGULATOR_LP8788 | |||
266 | This driver supports LP8788 voltage regulator chip. | 266 | This driver supports LP8788 voltage regulator chip. |
267 | 267 | ||
268 | config REGULATOR_MAX14577 | 268 | config REGULATOR_MAX14577 |
269 | tristate "Maxim 14577 regulator" | 269 | tristate "Maxim 14577/77836 regulator" |
270 | depends on MFD_MAX14577 | 270 | depends on MFD_MAX14577 |
271 | help | 271 | help |
272 | This driver controls a Maxim 14577 regulator via I2C bus. | 272 | This driver controls a Maxim MAX14577/77836 regulator via I2C bus. |
273 | The regulators include safeout LDO and current regulator 'CHARGER'. | 273 | The MAX14577 regulators include safeout LDO and charger current |
274 | regulator. The MAX77836 has two additional LDOs. | ||
274 | 275 | ||
275 | config REGULATOR_MAX1586 | 276 | config REGULATOR_MAX1586 |
276 | tristate "Maxim 1586/1587 voltage regulator" | 277 | tristate "Maxim 1586/1587 voltage regulator" |
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index b1033d30b504..d3787e11f535 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #include <linux/regulator/of_regulator.h> | ||
22 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
24 | 25 | ||
@@ -178,6 +179,42 @@ static const struct regulator_init_data arizona_ldo1_default = { | |||
178 | .num_consumer_supplies = 1, | 179 | .num_consumer_supplies = 1, |
179 | }; | 180 | }; |
180 | 181 | ||
182 | static int arizona_ldo1_of_get_pdata(struct arizona *arizona, | ||
183 | struct regulator_config *config) | ||
184 | { | ||
185 | struct arizona_pdata *pdata = &arizona->pdata; | ||
186 | struct arizona_ldo1 *ldo1 = config->driver_data; | ||
187 | struct device_node *init_node, *dcvdd_node; | ||
188 | struct regulator_init_data *init_data; | ||
189 | |||
190 | pdata->ldoena = arizona_of_get_named_gpio(arizona, "wlf,ldoena", true); | ||
191 | |||
192 | init_node = of_get_child_by_name(arizona->dev->of_node, "ldo1"); | ||
193 | dcvdd_node = of_parse_phandle(arizona->dev->of_node, "DCVDD-supply", 0); | ||
194 | |||
195 | if (init_node) { | ||
196 | config->of_node = init_node; | ||
197 | |||
198 | init_data = of_get_regulator_init_data(arizona->dev, init_node); | ||
199 | |||
200 | if (init_data) { | ||
201 | init_data->consumer_supplies = &ldo1->supply; | ||
202 | init_data->num_consumer_supplies = 1; | ||
203 | |||
204 | if (dcvdd_node && dcvdd_node != init_node) | ||
205 | arizona->external_dcvdd = true; | ||
206 | |||
207 | pdata->ldo1 = init_data; | ||
208 | } | ||
209 | } else if (dcvdd_node) { | ||
210 | arizona->external_dcvdd = true; | ||
211 | } | ||
212 | |||
213 | of_node_put(dcvdd_node); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
181 | static int arizona_ldo1_probe(struct platform_device *pdev) | 218 | static int arizona_ldo1_probe(struct platform_device *pdev) |
182 | { | 219 | { |
183 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 220 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
@@ -186,6 +223,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
186 | struct arizona_ldo1 *ldo1; | 223 | struct arizona_ldo1 *ldo1; |
187 | int ret; | 224 | int ret; |
188 | 225 | ||
226 | arizona->external_dcvdd = false; | ||
227 | |||
189 | ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); | 228 | ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); |
190 | if (!ldo1) | 229 | if (!ldo1) |
191 | return -ENOMEM; | 230 | return -ENOMEM; |
@@ -216,6 +255,15 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
216 | config.dev = arizona->dev; | 255 | config.dev = arizona->dev; |
217 | config.driver_data = ldo1; | 256 | config.driver_data = ldo1; |
218 | config.regmap = arizona->regmap; | 257 | config.regmap = arizona->regmap; |
258 | |||
259 | if (IS_ENABLED(CONFIG_OF)) { | ||
260 | if (!dev_get_platdata(arizona->dev)) { | ||
261 | ret = arizona_ldo1_of_get_pdata(arizona, &config); | ||
262 | if (ret < 0) | ||
263 | return ret; | ||
264 | } | ||
265 | } | ||
266 | |||
219 | config.ena_gpio = arizona->pdata.ldoena; | 267 | config.ena_gpio = arizona->pdata.ldoena; |
220 | 268 | ||
221 | if (arizona->pdata.ldo1) | 269 | if (arizona->pdata.ldo1) |
@@ -223,6 +271,13 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
223 | else | 271 | else |
224 | config.init_data = &ldo1->init_data; | 272 | config.init_data = &ldo1->init_data; |
225 | 273 | ||
274 | /* | ||
275 | * LDO1 can only be used to supply DCVDD so if it has no | ||
276 | * consumers then DCVDD is supplied externally. | ||
277 | */ | ||
278 | if (config.init_data->num_consumer_supplies == 0) | ||
279 | arizona->external_dcvdd = true; | ||
280 | |||
226 | ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); | 281 | ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); |
227 | if (IS_ERR(ldo1->regulator)) { | 282 | if (IS_ERR(ldo1->regulator)) { |
228 | ret = PTR_ERR(ldo1->regulator); | 283 | ret = PTR_ERR(ldo1->regulator); |
@@ -231,6 +286,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
231 | return ret; | 286 | return ret; |
232 | } | 287 | } |
233 | 288 | ||
289 | of_node_put(config.of_node); | ||
290 | |||
234 | platform_set_drvdata(pdev, ldo1); | 291 | platform_set_drvdata(pdev, ldo1); |
235 | 292 | ||
236 | return 0; | 293 | return 0; |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 6fdd9bf6927f..b80ebbe88bac 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #include <linux/regulator/of_regulator.h> | ||
22 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
@@ -195,6 +196,32 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { | |||
195 | .num_consumer_supplies = 1, | 196 | .num_consumer_supplies = 1, |
196 | }; | 197 | }; |
197 | 198 | ||
199 | static int arizona_micsupp_of_get_pdata(struct arizona *arizona, | ||
200 | struct regulator_config *config) | ||
201 | { | ||
202 | struct arizona_pdata *pdata = &arizona->pdata; | ||
203 | struct arizona_micsupp *micsupp = config->driver_data; | ||
204 | struct device_node *np; | ||
205 | struct regulator_init_data *init_data; | ||
206 | |||
207 | np = of_get_child_by_name(arizona->dev->of_node, "micvdd"); | ||
208 | |||
209 | if (np) { | ||
210 | config->of_node = np; | ||
211 | |||
212 | init_data = of_get_regulator_init_data(arizona->dev, np); | ||
213 | |||
214 | if (init_data) { | ||
215 | init_data->consumer_supplies = &micsupp->supply; | ||
216 | init_data->num_consumer_supplies = 1; | ||
217 | |||
218 | pdata->micvdd = init_data; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
198 | static int arizona_micsupp_probe(struct platform_device *pdev) | 225 | static int arizona_micsupp_probe(struct platform_device *pdev) |
199 | { | 226 | { |
200 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 227 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
@@ -234,6 +261,14 @@ static int arizona_micsupp_probe(struct platform_device *pdev) | |||
234 | config.driver_data = micsupp; | 261 | config.driver_data = micsupp; |
235 | config.regmap = arizona->regmap; | 262 | config.regmap = arizona->regmap; |
236 | 263 | ||
264 | if (IS_ENABLED(CONFIG_OF)) { | ||
265 | if (!dev_get_platdata(arizona->dev)) { | ||
266 | ret = arizona_micsupp_of_get_pdata(arizona, &config); | ||
267 | if (ret < 0) | ||
268 | return ret; | ||
269 | } | ||
270 | } | ||
271 | |||
237 | if (arizona->pdata.micvdd) | 272 | if (arizona->pdata.micvdd) |
238 | config.init_data = arizona->pdata.micvdd; | 273 | config.init_data = arizona->pdata.micvdd; |
239 | else | 274 | else |
@@ -253,6 +288,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) | |||
253 | return ret; | 288 | return ret; |
254 | } | 289 | } |
255 | 290 | ||
291 | of_node_put(config.of_node); | ||
292 | |||
256 | platform_set_drvdata(pdev, micsupp); | 293 | platform_set_drvdata(pdev, micsupp); |
257 | 294 | ||
258 | return 0; | 295 | return 0; |
diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index ed60baaeceec..5d9c605cf534 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * max14577.c - Regulator driver for the Maxim 14577 | 2 | * max14577.c - Regulator driver for the Maxim 14577/77836 |
3 | * | 3 | * |
4 | * Copyright (C) 2013,2014 Samsung Electronics | 4 | * Copyright (C) 2013,2014 Samsung Electronics |
5 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 5 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> |
@@ -22,6 +22,42 @@ | |||
22 | #include <linux/mfd/max14577-private.h> | 22 | #include <linux/mfd/max14577-private.h> |
23 | #include <linux/regulator/of_regulator.h> | 23 | #include <linux/regulator/of_regulator.h> |
24 | 24 | ||
25 | /* | ||
26 | * Valid limits of current for max14577 and max77836 chargers. | ||
27 | * They must correspond to MBCICHWRCL and MBCICHWRCH fields in CHGCTRL4 | ||
28 | * register for given chipset. | ||
29 | */ | ||
30 | struct maxim_charger_current { | ||
31 | /* Minimal current, set in CHGCTRL4/MBCICHWRCL, uA */ | ||
32 | unsigned int min; | ||
33 | /* | ||
34 | * Minimal current when high setting is active, | ||
35 | * set in CHGCTRL4/MBCICHWRCH, uA | ||
36 | */ | ||
37 | unsigned int high_start; | ||
38 | /* Value of one step in high setting, uA */ | ||
39 | unsigned int high_step; | ||
40 | /* Maximum current of high setting, uA */ | ||
41 | unsigned int max; | ||
42 | }; | ||
43 | |||
44 | /* Table of valid charger currents for different Maxim chipsets */ | ||
45 | static const struct maxim_charger_current maxim_charger_currents[] = { | ||
46 | [MAXIM_DEVICE_TYPE_UNKNOWN] = { 0, 0, 0, 0 }, | ||
47 | [MAXIM_DEVICE_TYPE_MAX14577] = { | ||
48 | .min = MAX14577_REGULATOR_CURRENT_LIMIT_MIN, | ||
49 | .high_start = MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START, | ||
50 | .high_step = MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP, | ||
51 | .max = MAX14577_REGULATOR_CURRENT_LIMIT_MAX, | ||
52 | }, | ||
53 | [MAXIM_DEVICE_TYPE_MAX77836] = { | ||
54 | .min = MAX77836_REGULATOR_CURRENT_LIMIT_MIN, | ||
55 | .high_start = MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_START, | ||
56 | .high_step = MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_STEP, | ||
57 | .max = MAX77836_REGULATOR_CURRENT_LIMIT_MAX, | ||
58 | }, | ||
59 | }; | ||
60 | |||
25 | static int max14577_reg_is_enabled(struct regulator_dev *rdev) | 61 | static int max14577_reg_is_enabled(struct regulator_dev *rdev) |
26 | { | 62 | { |
27 | int rid = rdev_get_id(rdev); | 63 | int rid = rdev_get_id(rdev); |
@@ -47,6 +83,9 @@ static int max14577_reg_get_current_limit(struct regulator_dev *rdev) | |||
47 | { | 83 | { |
48 | u8 reg_data; | 84 | u8 reg_data; |
49 | struct regmap *rmap = rdev->regmap; | 85 | struct regmap *rmap = rdev->regmap; |
86 | struct max14577 *max14577 = rdev_get_drvdata(rdev); | ||
87 | const struct maxim_charger_current *limits = | ||
88 | &maxim_charger_currents[max14577->dev_type]; | ||
50 | 89 | ||
51 | if (rdev_get_id(rdev) != MAX14577_CHARGER) | 90 | if (rdev_get_id(rdev) != MAX14577_CHARGER) |
52 | return -EINVAL; | 91 | return -EINVAL; |
@@ -54,12 +93,11 @@ static int max14577_reg_get_current_limit(struct regulator_dev *rdev) | |||
54 | max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL4, ®_data); | 93 | max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL4, ®_data); |
55 | 94 | ||
56 | if ((reg_data & CHGCTRL4_MBCICHWRCL_MASK) == 0) | 95 | if ((reg_data & CHGCTRL4_MBCICHWRCL_MASK) == 0) |
57 | return MAX14577_REGULATOR_CURRENT_LIMIT_MIN; | 96 | return limits->min; |
58 | 97 | ||
59 | reg_data = ((reg_data & CHGCTRL4_MBCICHWRCH_MASK) >> | 98 | reg_data = ((reg_data & CHGCTRL4_MBCICHWRCH_MASK) >> |
60 | CHGCTRL4_MBCICHWRCH_SHIFT); | 99 | CHGCTRL4_MBCICHWRCH_SHIFT); |
61 | return MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START + | 100 | return limits->high_start + reg_data * limits->high_step; |
62 | reg_data * MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP; | ||
63 | } | 101 | } |
64 | 102 | ||
65 | static int max14577_reg_set_current_limit(struct regulator_dev *rdev, | 103 | static int max14577_reg_set_current_limit(struct regulator_dev *rdev, |
@@ -67,33 +105,39 @@ static int max14577_reg_set_current_limit(struct regulator_dev *rdev, | |||
67 | { | 105 | { |
68 | int i, current_bits = 0xf; | 106 | int i, current_bits = 0xf; |
69 | u8 reg_data; | 107 | u8 reg_data; |
108 | struct max14577 *max14577 = rdev_get_drvdata(rdev); | ||
109 | const struct maxim_charger_current *limits = | ||
110 | &maxim_charger_currents[max14577->dev_type]; | ||
70 | 111 | ||
71 | if (rdev_get_id(rdev) != MAX14577_CHARGER) | 112 | if (rdev_get_id(rdev) != MAX14577_CHARGER) |
72 | return -EINVAL; | 113 | return -EINVAL; |
73 | 114 | ||
74 | if (min_uA > MAX14577_REGULATOR_CURRENT_LIMIT_MAX || | 115 | if (min_uA > limits->max || max_uA < limits->min) |
75 | max_uA < MAX14577_REGULATOR_CURRENT_LIMIT_MIN) | ||
76 | return -EINVAL; | 116 | return -EINVAL; |
77 | 117 | ||
78 | if (max_uA < MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START) { | 118 | if (max_uA < limits->high_start) { |
79 | /* Less than 200 mA, so set 90mA (turn only Low Bit off) */ | 119 | /* |
120 | * Less than high_start, | ||
121 | * so set the minimal current (turn only Low Bit off) | ||
122 | */ | ||
80 | u8 reg_data = 0x0 << CHGCTRL4_MBCICHWRCL_SHIFT; | 123 | u8 reg_data = 0x0 << CHGCTRL4_MBCICHWRCL_SHIFT; |
81 | return max14577_update_reg(rdev->regmap, | 124 | return max14577_update_reg(rdev->regmap, |
82 | MAX14577_CHG_REG_CHG_CTRL4, | 125 | MAX14577_CHG_REG_CHG_CTRL4, |
83 | CHGCTRL4_MBCICHWRCL_MASK, reg_data); | 126 | CHGCTRL4_MBCICHWRCL_MASK, reg_data); |
84 | } | 127 | } |
85 | 128 | ||
86 | /* max_uA is in range: <LIMIT_HIGH_START, inifinite>, so search for | 129 | /* |
87 | * valid current starting from LIMIT_MAX. */ | 130 | * max_uA is in range: <high_start, inifinite>, so search for |
88 | for (i = MAX14577_REGULATOR_CURRENT_LIMIT_MAX; | 131 | * valid current starting from maximum current. |
89 | i >= MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START; | 132 | */ |
90 | i -= MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP) { | 133 | for (i = limits->max; i >= limits->high_start; i -= limits->high_step) { |
91 | if (i <= max_uA) | 134 | if (i <= max_uA) |
92 | break; | 135 | break; |
93 | current_bits--; | 136 | current_bits--; |
94 | } | 137 | } |
95 | BUG_ON(current_bits < 0); /* Cannot happen */ | 138 | BUG_ON(current_bits < 0); /* Cannot happen */ |
96 | /* Turn Low Bit on (use range 200mA-950 mA) */ | 139 | |
140 | /* Turn Low Bit on (use range high_start-max)... */ | ||
97 | reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT; | 141 | reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT; |
98 | /* and set proper High Bits */ | 142 | /* and set proper High Bits */ |
99 | reg_data |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT; | 143 | reg_data |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT; |
@@ -118,7 +162,7 @@ static struct regulator_ops max14577_charger_ops = { | |||
118 | .set_current_limit = max14577_reg_set_current_limit, | 162 | .set_current_limit = max14577_reg_set_current_limit, |
119 | }; | 163 | }; |
120 | 164 | ||
121 | static const struct regulator_desc supported_regulators[] = { | 165 | static const struct regulator_desc max14577_supported_regulators[] = { |
122 | [MAX14577_SAFEOUT] = { | 166 | [MAX14577_SAFEOUT] = { |
123 | .name = "SAFEOUT", | 167 | .name = "SAFEOUT", |
124 | .id = MAX14577_SAFEOUT, | 168 | .id = MAX14577_SAFEOUT, |
@@ -141,16 +185,88 @@ static const struct regulator_desc supported_regulators[] = { | |||
141 | }, | 185 | }, |
142 | }; | 186 | }; |
143 | 187 | ||
188 | static struct regulator_ops max77836_ldo_ops = { | ||
189 | .is_enabled = regulator_is_enabled_regmap, | ||
190 | .enable = regulator_enable_regmap, | ||
191 | .disable = regulator_disable_regmap, | ||
192 | .list_voltage = regulator_list_voltage_linear, | ||
193 | .map_voltage = regulator_map_voltage_linear, | ||
194 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
195 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
196 | /* TODO: add .set_suspend_mode */ | ||
197 | }; | ||
198 | |||
199 | static const struct regulator_desc max77836_supported_regulators[] = { | ||
200 | [MAX14577_SAFEOUT] = { | ||
201 | .name = "SAFEOUT", | ||
202 | .id = MAX14577_SAFEOUT, | ||
203 | .ops = &max14577_safeout_ops, | ||
204 | .type = REGULATOR_VOLTAGE, | ||
205 | .owner = THIS_MODULE, | ||
206 | .n_voltages = 1, | ||
207 | .min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE, | ||
208 | .enable_reg = MAX14577_REG_CONTROL2, | ||
209 | .enable_mask = CTRL2_SFOUTORD_MASK, | ||
210 | }, | ||
211 | [MAX14577_CHARGER] = { | ||
212 | .name = "CHARGER", | ||
213 | .id = MAX14577_CHARGER, | ||
214 | .ops = &max14577_charger_ops, | ||
215 | .type = REGULATOR_CURRENT, | ||
216 | .owner = THIS_MODULE, | ||
217 | .enable_reg = MAX14577_CHG_REG_CHG_CTRL2, | ||
218 | .enable_mask = CHGCTRL2_MBCHOSTEN_MASK, | ||
219 | }, | ||
220 | [MAX77836_LDO1] = { | ||
221 | .name = "LDO1", | ||
222 | .id = MAX77836_LDO1, | ||
223 | .ops = &max77836_ldo_ops, | ||
224 | .type = REGULATOR_VOLTAGE, | ||
225 | .owner = THIS_MODULE, | ||
226 | .n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, | ||
227 | .min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, | ||
228 | .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, | ||
229 | .enable_reg = MAX77836_LDO_REG_CNFG1_LDO1, | ||
230 | .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, | ||
231 | .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO1, | ||
232 | .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, | ||
233 | }, | ||
234 | [MAX77836_LDO2] = { | ||
235 | .name = "LDO2", | ||
236 | .id = MAX77836_LDO2, | ||
237 | .ops = &max77836_ldo_ops, | ||
238 | .type = REGULATOR_VOLTAGE, | ||
239 | .owner = THIS_MODULE, | ||
240 | .n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, | ||
241 | .min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, | ||
242 | .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, | ||
243 | .enable_reg = MAX77836_LDO_REG_CNFG1_LDO2, | ||
244 | .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, | ||
245 | .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO2, | ||
246 | .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, | ||
247 | }, | ||
248 | }; | ||
249 | |||
144 | #ifdef CONFIG_OF | 250 | #ifdef CONFIG_OF |
145 | static struct of_regulator_match max14577_regulator_matches[] = { | 251 | static struct of_regulator_match max14577_regulator_matches[] = { |
146 | { .name = "SAFEOUT", }, | 252 | { .name = "SAFEOUT", }, |
147 | { .name = "CHARGER", }, | 253 | { .name = "CHARGER", }, |
148 | }; | 254 | }; |
149 | 255 | ||
150 | static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) | 256 | static struct of_regulator_match max77836_regulator_matches[] = { |
257 | { .name = "SAFEOUT", }, | ||
258 | { .name = "CHARGER", }, | ||
259 | { .name = "LDO1", }, | ||
260 | { .name = "LDO2", }, | ||
261 | }; | ||
262 | |||
263 | static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev, | ||
264 | enum maxim_device_type dev_type) | ||
151 | { | 265 | { |
152 | int ret; | 266 | int ret; |
153 | struct device_node *np; | 267 | struct device_node *np; |
268 | struct of_regulator_match *regulator_matches; | ||
269 | unsigned int regulator_matches_size; | ||
154 | 270 | ||
155 | np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); | 271 | np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); |
156 | if (!np) { | 272 | if (!np) { |
@@ -158,8 +274,19 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) | |||
158 | return -EINVAL; | 274 | return -EINVAL; |
159 | } | 275 | } |
160 | 276 | ||
161 | ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches, | 277 | switch (dev_type) { |
162 | MAX14577_REG_MAX); | 278 | case MAXIM_DEVICE_TYPE_MAX77836: |
279 | regulator_matches = max77836_regulator_matches; | ||
280 | regulator_matches_size = ARRAY_SIZE(max77836_regulator_matches); | ||
281 | break; | ||
282 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
283 | default: | ||
284 | regulator_matches = max14577_regulator_matches; | ||
285 | regulator_matches_size = ARRAY_SIZE(max14577_regulator_matches); | ||
286 | } | ||
287 | |||
288 | ret = of_regulator_match(&pdev->dev, np, regulator_matches, | ||
289 | regulator_matches_size); | ||
163 | if (ret < 0) | 290 | if (ret < 0) |
164 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); | 291 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); |
165 | else | 292 | else |
@@ -170,31 +297,74 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) | |||
170 | return ret; | 297 | return ret; |
171 | } | 298 | } |
172 | 299 | ||
173 | static inline struct regulator_init_data *match_init_data(int index) | 300 | static inline struct regulator_init_data *match_init_data(int index, |
301 | enum maxim_device_type dev_type) | ||
174 | { | 302 | { |
175 | return max14577_regulator_matches[index].init_data; | 303 | switch (dev_type) { |
304 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
305 | return max77836_regulator_matches[index].init_data; | ||
306 | |||
307 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
308 | default: | ||
309 | return max14577_regulator_matches[index].init_data; | ||
310 | } | ||
176 | } | 311 | } |
177 | 312 | ||
178 | static inline struct device_node *match_of_node(int index) | 313 | static inline struct device_node *match_of_node(int index, |
314 | enum maxim_device_type dev_type) | ||
179 | { | 315 | { |
180 | return max14577_regulator_matches[index].of_node; | 316 | switch (dev_type) { |
317 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
318 | return max77836_regulator_matches[index].of_node; | ||
319 | |||
320 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
321 | default: | ||
322 | return max14577_regulator_matches[index].of_node; | ||
323 | } | ||
181 | } | 324 | } |
182 | #else /* CONFIG_OF */ | 325 | #else /* CONFIG_OF */ |
183 | static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) | 326 | static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev, |
327 | enum maxim_device_type dev_type) | ||
184 | { | 328 | { |
185 | return 0; | 329 | return 0; |
186 | } | 330 | } |
187 | static inline struct regulator_init_data *match_init_data(int index) | 331 | static inline struct regulator_init_data *match_init_data(int index, |
332 | enum maxim_device_type dev_type) | ||
188 | { | 333 | { |
189 | return NULL; | 334 | return NULL; |
190 | } | 335 | } |
191 | 336 | ||
192 | static inline struct device_node *match_of_node(int index) | 337 | static inline struct device_node *match_of_node(int index, |
338 | enum maxim_device_type dev_type) | ||
193 | { | 339 | { |
194 | return NULL; | 340 | return NULL; |
195 | } | 341 | } |
196 | #endif /* CONFIG_OF */ | 342 | #endif /* CONFIG_OF */ |
197 | 343 | ||
344 | /** | ||
345 | * Registers for regulators of max77836 use different I2C slave addresses so | ||
346 | * different regmaps must be used for them. | ||
347 | * | ||
348 | * Returns proper regmap for accessing regulator passed by id. | ||
349 | */ | ||
350 | static struct regmap *max14577_get_regmap(struct max14577 *max14577, | ||
351 | int reg_id) | ||
352 | { | ||
353 | switch (max14577->dev_type) { | ||
354 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
355 | switch (reg_id) { | ||
356 | case MAX77836_SAFEOUT ... MAX77836_CHARGER: | ||
357 | return max14577->regmap; | ||
358 | default: | ||
359 | /* MAX77836_LDO1 ... MAX77836_LDO2 */ | ||
360 | return max14577->regmap_pmic; | ||
361 | } | ||
362 | |||
363 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
364 | default: | ||
365 | return max14577->regmap; | ||
366 | } | ||
367 | } | ||
198 | 368 | ||
199 | static int max14577_regulator_probe(struct platform_device *pdev) | 369 | static int max14577_regulator_probe(struct platform_device *pdev) |
200 | { | 370 | { |
@@ -202,15 +372,29 @@ static int max14577_regulator_probe(struct platform_device *pdev) | |||
202 | struct max14577_platform_data *pdata = dev_get_platdata(max14577->dev); | 372 | struct max14577_platform_data *pdata = dev_get_platdata(max14577->dev); |
203 | int i, ret; | 373 | int i, ret; |
204 | struct regulator_config config = {}; | 374 | struct regulator_config config = {}; |
375 | const struct regulator_desc *supported_regulators; | ||
376 | unsigned int supported_regulators_size; | ||
377 | enum maxim_device_type dev_type = max14577->dev_type; | ||
205 | 378 | ||
206 | ret = max14577_regulator_dt_parse_pdata(pdev); | 379 | ret = max14577_regulator_dt_parse_pdata(pdev, dev_type); |
207 | if (ret) | 380 | if (ret) |
208 | return ret; | 381 | return ret; |
209 | 382 | ||
383 | switch (dev_type) { | ||
384 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
385 | supported_regulators = max77836_supported_regulators; | ||
386 | supported_regulators_size = ARRAY_SIZE(max77836_supported_regulators); | ||
387 | break; | ||
388 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
389 | default: | ||
390 | supported_regulators = max14577_supported_regulators; | ||
391 | supported_regulators_size = ARRAY_SIZE(max14577_supported_regulators); | ||
392 | } | ||
393 | |||
210 | config.dev = &pdev->dev; | 394 | config.dev = &pdev->dev; |
211 | config.regmap = max14577->regmap; | 395 | config.driver_data = max14577; |
212 | 396 | ||
213 | for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) { | 397 | for (i = 0; i < supported_regulators_size; i++) { |
214 | struct regulator_dev *regulator; | 398 | struct regulator_dev *regulator; |
215 | /* | 399 | /* |
216 | * Index of supported_regulators[] is also the id and must | 400 | * Index of supported_regulators[] is also the id and must |
@@ -220,17 +404,19 @@ static int max14577_regulator_probe(struct platform_device *pdev) | |||
220 | config.init_data = pdata->regulators[i].initdata; | 404 | config.init_data = pdata->regulators[i].initdata; |
221 | config.of_node = pdata->regulators[i].of_node; | 405 | config.of_node = pdata->regulators[i].of_node; |
222 | } else { | 406 | } else { |
223 | config.init_data = match_init_data(i); | 407 | config.init_data = match_init_data(i, dev_type); |
224 | config.of_node = match_of_node(i); | 408 | config.of_node = match_of_node(i, dev_type); |
225 | } | 409 | } |
410 | config.regmap = max14577_get_regmap(max14577, | ||
411 | supported_regulators[i].id); | ||
226 | 412 | ||
227 | regulator = devm_regulator_register(&pdev->dev, | 413 | regulator = devm_regulator_register(&pdev->dev, |
228 | &supported_regulators[i], &config); | 414 | &supported_regulators[i], &config); |
229 | if (IS_ERR(regulator)) { | 415 | if (IS_ERR(regulator)) { |
230 | ret = PTR_ERR(regulator); | 416 | ret = PTR_ERR(regulator); |
231 | dev_err(&pdev->dev, | 417 | dev_err(&pdev->dev, |
232 | "Regulator init failed for ID %d with error: %d\n", | 418 | "Regulator init failed for %d/%s with error: %d\n", |
233 | i, ret); | 419 | i, supported_regulators[i].name, ret); |
234 | return ret; | 420 | return ret; |
235 | } | 421 | } |
236 | } | 422 | } |
@@ -238,20 +424,41 @@ static int max14577_regulator_probe(struct platform_device *pdev) | |||
238 | return ret; | 424 | return ret; |
239 | } | 425 | } |
240 | 426 | ||
427 | static const struct platform_device_id max14577_regulator_id[] = { | ||
428 | { "max14577-regulator", MAXIM_DEVICE_TYPE_MAX14577, }, | ||
429 | { "max77836-regulator", MAXIM_DEVICE_TYPE_MAX77836, }, | ||
430 | { } | ||
431 | }; | ||
432 | MODULE_DEVICE_TABLE(platform, max14577_regulator_id); | ||
433 | |||
241 | static struct platform_driver max14577_regulator_driver = { | 434 | static struct platform_driver max14577_regulator_driver = { |
242 | .driver = { | 435 | .driver = { |
243 | .owner = THIS_MODULE, | 436 | .owner = THIS_MODULE, |
244 | .name = "max14577-regulator", | 437 | .name = "max14577-regulator", |
245 | }, | 438 | }, |
246 | .probe = max14577_regulator_probe, | 439 | .probe = max14577_regulator_probe, |
440 | .id_table = max14577_regulator_id, | ||
247 | }; | 441 | }; |
248 | 442 | ||
249 | static int __init max14577_regulator_init(void) | 443 | static int __init max14577_regulator_init(void) |
250 | { | 444 | { |
445 | /* Check for valid values for charger */ | ||
251 | BUILD_BUG_ON(MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START + | 446 | BUILD_BUG_ON(MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START + |
252 | MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP * 0xf != | 447 | MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP * 0xf != |
253 | MAX14577_REGULATOR_CURRENT_LIMIT_MAX); | 448 | MAX14577_REGULATOR_CURRENT_LIMIT_MAX); |
254 | BUILD_BUG_ON(ARRAY_SIZE(supported_regulators) != MAX14577_REG_MAX); | 449 | BUILD_BUG_ON(MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_START + |
450 | MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_STEP * 0xf != | ||
451 | MAX77836_REGULATOR_CURRENT_LIMIT_MAX); | ||
452 | /* Valid charger current values must be provided for each chipset */ | ||
453 | BUILD_BUG_ON(ARRAY_SIZE(maxim_charger_currents) != MAXIM_DEVICE_TYPE_NUM); | ||
454 | |||
455 | BUILD_BUG_ON(ARRAY_SIZE(max14577_supported_regulators) != MAX14577_REGULATOR_NUM); | ||
456 | BUILD_BUG_ON(ARRAY_SIZE(max77836_supported_regulators) != MAX77836_REGULATOR_NUM); | ||
457 | |||
458 | BUILD_BUG_ON(MAX77836_REGULATOR_LDO_VOLTAGE_MIN + | ||
459 | (MAX77836_REGULATOR_LDO_VOLTAGE_STEP * | ||
460 | (MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM - 1)) != | ||
461 | MAX77836_REGULATOR_LDO_VOLTAGE_MAX); | ||
255 | 462 | ||
256 | return platform_driver_register(&max14577_regulator_driver); | 463 | return platform_driver_register(&max14577_regulator_driver); |
257 | } | 464 | } |
@@ -264,6 +471,6 @@ static void __exit max14577_regulator_exit(void) | |||
264 | module_exit(max14577_regulator_exit); | 471 | module_exit(max14577_regulator_exit); |
265 | 472 | ||
266 | MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>"); | 473 | MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
267 | MODULE_DESCRIPTION("MAXIM 14577 regulator driver"); | 474 | MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); |
268 | MODULE_LICENSE("GPL"); | 475 | MODULE_LICENSE("GPL"); |
269 | MODULE_ALIAS("platform:max14577-regulator"); | 476 | MODULE_ALIAS("platform:max14577-regulator"); |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 32f38a63d944..e045b7fe5572 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -68,7 +68,7 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | |||
68 | return rdev_get_dev(rdev)->parent; | 68 | return rdev_get_dev(rdev)->parent; |
69 | } | 69 | } |
70 | 70 | ||
71 | static struct regulator_ops tps6586x_regulator_ops = { | 71 | static struct regulator_ops tps6586x_rw_regulator_ops = { |
72 | .list_voltage = regulator_list_voltage_table, | 72 | .list_voltage = regulator_list_voltage_table, |
73 | .map_voltage = regulator_map_voltage_ascend, | 73 | .map_voltage = regulator_map_voltage_ascend, |
74 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 74 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
@@ -79,6 +79,16 @@ static struct regulator_ops tps6586x_regulator_ops = { | |||
79 | .disable = regulator_disable_regmap, | 79 | .disable = regulator_disable_regmap, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static struct regulator_ops tps6586x_ro_regulator_ops = { | ||
83 | .list_voltage = regulator_list_voltage_table, | ||
84 | .map_voltage = regulator_map_voltage_ascend, | ||
85 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
86 | |||
87 | .is_enabled = regulator_is_enabled_regmap, | ||
88 | .enable = regulator_enable_regmap, | ||
89 | .disable = regulator_disable_regmap, | ||
90 | }; | ||
91 | |||
82 | static struct regulator_ops tps6586x_sys_regulator_ops = { | 92 | static struct regulator_ops tps6586x_sys_regulator_ops = { |
83 | }; | 93 | }; |
84 | 94 | ||
@@ -106,6 +116,13 @@ static const unsigned int tps6586x_sm2_voltages[] = { | |||
106 | 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, | 116 | 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, |
107 | }; | 117 | }; |
108 | 118 | ||
119 | static int tps658640_sm2_voltages[] = { | ||
120 | 2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000, | ||
121 | 2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000, | ||
122 | 2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, | ||
123 | 3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, | ||
124 | }; | ||
125 | |||
109 | static const unsigned int tps658643_sm2_voltages[] = { | 126 | static const unsigned int tps658643_sm2_voltages[] = { |
110 | 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, | 127 | 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, |
111 | 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, | 128 | 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, |
@@ -120,12 +137,16 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
120 | 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, | 137 | 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, |
121 | }; | 138 | }; |
122 | 139 | ||
123 | #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ | 140 | static int tps658640_rtc_voltages[] = { |
141 | 2500000, 2850000, 3100000, 3300000, | ||
142 | }; | ||
143 | |||
144 | #define TPS6586X_REGULATOR(_id, _ops, _pin_name, vdata, vreg, shift, nbits, \ | ||
124 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 145 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
125 | .desc = { \ | 146 | .desc = { \ |
126 | .supply_name = _pin_name, \ | 147 | .supply_name = _pin_name, \ |
127 | .name = "REG-" #_id, \ | 148 | .name = "REG-" #_id, \ |
128 | .ops = &tps6586x_regulator_ops, \ | 149 | .ops = &tps6586x_## _ops ## _regulator_ops, \ |
129 | .type = REGULATOR_VOLTAGE, \ | 150 | .type = REGULATOR_VOLTAGE, \ |
130 | .id = TPS6586X_ID_##_id, \ | 151 | .id = TPS6586X_ID_##_id, \ |
131 | .n_voltages = ARRAY_SIZE(vdata##_voltages), \ | 152 | .n_voltages = ARRAY_SIZE(vdata##_voltages), \ |
@@ -146,14 +167,21 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
146 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ | 167 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ |
147 | ereg0, ebit0, ereg1, ebit1) \ | 168 | ereg0, ebit0, ereg1, ebit1) \ |
148 | { \ | 169 | { \ |
149 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 170 | TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \ |
171 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ | ||
172 | } | ||
173 | |||
174 | #define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits, \ | ||
175 | ereg0, ebit0, ereg1, ebit1) \ | ||
176 | { \ | ||
177 | TPS6586X_REGULATOR(_id, ro, _pname, vdata, vreg, shift, nbits, \ | ||
150 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ | 178 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ |
151 | } | 179 | } |
152 | 180 | ||
153 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ | 181 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ |
154 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 182 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
155 | { \ | 183 | { \ |
156 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 184 | TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \ |
157 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 185 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
158 | } | 186 | } |
159 | 187 | ||
@@ -207,6 +235,26 @@ static struct tps6586x_regulator tps658623_regulator[] = { | |||
207 | END, 7), | 235 | END, 7), |
208 | }; | 236 | }; |
209 | 237 | ||
238 | static struct tps6586x_regulator tps658640_regulator[] = { | ||
239 | TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo0, SUPPLYV4, 0, 3, | ||
240 | ENC, 2, END, 2), | ||
241 | TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo0, SUPPLYV6, 0, 3, | ||
242 | ENE, 6, ENE, 6), | ||
243 | TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo0, SUPPLYV3, 0, 3, | ||
244 | ENC, 4, END, 4), | ||
245 | TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo0, SUPPLYV3, 3, 3, | ||
246 | ENC, 5, END, 5), | ||
247 | TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo0, SUPPLYV2, 5, 3, | ||
248 | ENC, 6, END, 6), | ||
249 | TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3, | ||
250 | ENE, 7, ENE, 7), | ||
251 | TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5, | ||
252 | ENC, 7, END, 7), | ||
253 | |||
254 | TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2, | ||
255 | V4, 7, V4, 7), | ||
256 | }; | ||
257 | |||
210 | static struct tps6586x_regulator tps658643_regulator[] = { | 258 | static struct tps6586x_regulator tps658643_regulator[] = { |
211 | TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, | 259 | TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, |
212 | END, 7), | 260 | END, 7), |
@@ -295,6 +343,11 @@ static struct tps6586x_regulator *find_regulator_info(int id, int version) | |||
295 | table = tps658623_regulator; | 343 | table = tps658623_regulator; |
296 | num = ARRAY_SIZE(tps658623_regulator); | 344 | num = ARRAY_SIZE(tps658623_regulator); |
297 | break; | 345 | break; |
346 | case TPS658640: | ||
347 | case TPS658640v2: | ||
348 | table = tps658640_regulator; | ||
349 | num = ARRAY_SIZE(tps658640_regulator); | ||
350 | break; | ||
298 | case TPS658643: | 351 | case TPS658643: |
299 | table = tps658643_regulator; | 352 | table = tps658643_regulator; |
300 | num = ARRAY_SIZE(tps658643_regulator); | 353 | num = ARRAY_SIZE(tps658643_regulator); |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 5ae5100c1f24..77a5fa191502 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -468,6 +468,27 @@ struct cpufreq_frequency_table { | |||
468 | * order */ | 468 | * order */ |
469 | }; | 469 | }; |
470 | 470 | ||
471 | bool cpufreq_next_valid(struct cpufreq_frequency_table **pos); | ||
472 | |||
473 | /* | ||
474 | * cpufreq_for_each_entry - iterate over a cpufreq_frequency_table | ||
475 | * @pos: the cpufreq_frequency_table * to use as a loop cursor. | ||
476 | * @table: the cpufreq_frequency_table * to iterate over. | ||
477 | */ | ||
478 | |||
479 | #define cpufreq_for_each_entry(pos, table) \ | ||
480 | for (pos = table; pos->frequency != CPUFREQ_TABLE_END; pos++) | ||
481 | |||
482 | /* | ||
483 | * cpufreq_for_each_valid_entry - iterate over a cpufreq_frequency_table | ||
484 | * excluding CPUFREQ_ENTRY_INVALID frequencies. | ||
485 | * @pos: the cpufreq_frequency_table * to use as a loop cursor. | ||
486 | * @table: the cpufreq_frequency_table * to iterate over. | ||
487 | */ | ||
488 | |||
489 | #define cpufreq_for_each_valid_entry(pos, table) \ | ||
490 | for (pos = table; cpufreq_next_valid(&pos); pos++) | ||
491 | |||
471 | int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, | 492 | int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, |
472 | struct cpufreq_frequency_table *table); | 493 | struct cpufreq_frequency_table *table); |
473 | 494 | ||
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index 5cf8b91ce996..6d9371f88875 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h | |||
@@ -124,4 +124,7 @@ int wm5102_patch(struct arizona *arizona); | |||
124 | int wm5110_patch(struct arizona *arizona); | 124 | int wm5110_patch(struct arizona *arizona); |
125 | int wm8997_patch(struct arizona *arizona); | 125 | int wm8997_patch(struct arizona *arizona); |
126 | 126 | ||
127 | extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
128 | bool mandatory); | ||
129 | |||
127 | #endif | 130 | #endif |
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h index c9b332fb0d5d..499253604026 100644 --- a/include/linux/mfd/max14577-private.h +++ b/include/linux/mfd/max14577-private.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * max14577-private.h - Common API for the Maxim 14577 internal sub chip | 2 | * max14577-private.h - Common API for the Maxim 14577/77836 internal sub chip |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> |
7 | * | 7 | * |
@@ -22,9 +22,19 @@ | |||
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
24 | 24 | ||
25 | #define MAX14577_REG_INVALID (0xff) | 25 | #define I2C_ADDR_PMIC (0x46 >> 1) |
26 | #define I2C_ADDR_MUIC (0x4A >> 1) | ||
27 | #define I2C_ADDR_FG (0x6C >> 1) | ||
26 | 28 | ||
27 | /* Slave addr = 0x4A: Interrupt */ | 29 | enum maxim_device_type { |
30 | MAXIM_DEVICE_TYPE_UNKNOWN = 0, | ||
31 | MAXIM_DEVICE_TYPE_MAX14577, | ||
32 | MAXIM_DEVICE_TYPE_MAX77836, | ||
33 | |||
34 | MAXIM_DEVICE_TYPE_NUM, | ||
35 | }; | ||
36 | |||
37 | /* Slave addr = 0x4A: MUIC and Charger */ | ||
28 | enum max14577_reg { | 38 | enum max14577_reg { |
29 | MAX14577_REG_DEVICEID = 0x00, | 39 | MAX14577_REG_DEVICEID = 0x00, |
30 | MAX14577_REG_INT1 = 0x01, | 40 | MAX14577_REG_INT1 = 0x01, |
@@ -74,20 +84,22 @@ enum max14577_muic_charger_type { | |||
74 | }; | 84 | }; |
75 | 85 | ||
76 | /* MAX14577 interrupts */ | 86 | /* MAX14577 interrupts */ |
77 | #define INT1_ADC_MASK (0x1 << 0) | 87 | #define MAX14577_INT1_ADC_MASK BIT(0) |
78 | #define INT1_ADCLOW_MASK (0x1 << 1) | 88 | #define MAX14577_INT1_ADCLOW_MASK BIT(1) |
79 | #define INT1_ADCERR_MASK (0x1 << 2) | 89 | #define MAX14577_INT1_ADCERR_MASK BIT(2) |
80 | 90 | #define MAX77836_INT1_ADC1K_MASK BIT(3) | |
81 | #define INT2_CHGTYP_MASK (0x1 << 0) | 91 | |
82 | #define INT2_CHGDETRUN_MASK (0x1 << 1) | 92 | #define MAX14577_INT2_CHGTYP_MASK BIT(0) |
83 | #define INT2_DCDTMR_MASK (0x1 << 2) | 93 | #define MAX14577_INT2_CHGDETRUN_MASK BIT(1) |
84 | #define INT2_DBCHG_MASK (0x1 << 3) | 94 | #define MAX14577_INT2_DCDTMR_MASK BIT(2) |
85 | #define INT2_VBVOLT_MASK (0x1 << 4) | 95 | #define MAX14577_INT2_DBCHG_MASK BIT(3) |
86 | 96 | #define MAX14577_INT2_VBVOLT_MASK BIT(4) | |
87 | #define INT3_EOC_MASK (0x1 << 0) | 97 | #define MAX77836_INT2_VIDRM_MASK BIT(5) |
88 | #define INT3_CGMBC_MASK (0x1 << 1) | 98 | |
89 | #define INT3_OVP_MASK (0x1 << 2) | 99 | #define MAX14577_INT3_EOC_MASK BIT(0) |
90 | #define INT3_MBCCHGERR_MASK (0x1 << 3) | 100 | #define MAX14577_INT3_CGMBC_MASK BIT(1) |
101 | #define MAX14577_INT3_OVP_MASK BIT(2) | ||
102 | #define MAX14577_INT3_MBCCHGERR_MASK BIT(3) | ||
91 | 103 | ||
92 | /* MAX14577 DEVICE ID register */ | 104 | /* MAX14577 DEVICE ID register */ |
93 | #define DEVID_VENDORID_SHIFT 0 | 105 | #define DEVID_VENDORID_SHIFT 0 |
@@ -99,9 +111,11 @@ enum max14577_muic_charger_type { | |||
99 | #define STATUS1_ADC_SHIFT 0 | 111 | #define STATUS1_ADC_SHIFT 0 |
100 | #define STATUS1_ADCLOW_SHIFT 5 | 112 | #define STATUS1_ADCLOW_SHIFT 5 |
101 | #define STATUS1_ADCERR_SHIFT 6 | 113 | #define STATUS1_ADCERR_SHIFT 6 |
114 | #define MAX77836_STATUS1_ADC1K_SHIFT 7 | ||
102 | #define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT) | 115 | #define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT) |
103 | #define STATUS1_ADCLOW_MASK (0x1 << STATUS1_ADCLOW_SHIFT) | 116 | #define STATUS1_ADCLOW_MASK BIT(STATUS1_ADCLOW_SHIFT) |
104 | #define STATUS1_ADCERR_MASK (0x1 << STATUS1_ADCERR_SHIFT) | 117 | #define STATUS1_ADCERR_MASK BIT(STATUS1_ADCERR_SHIFT) |
118 | #define MAX77836_STATUS1_ADC1K_MASK BIT(MAX77836_STATUS1_ADC1K_SHIFT) | ||
105 | 119 | ||
106 | /* MAX14577 STATUS2 register */ | 120 | /* MAX14577 STATUS2 register */ |
107 | #define STATUS2_CHGTYP_SHIFT 0 | 121 | #define STATUS2_CHGTYP_SHIFT 0 |
@@ -109,11 +123,13 @@ enum max14577_muic_charger_type { | |||
109 | #define STATUS2_DCDTMR_SHIFT 4 | 123 | #define STATUS2_DCDTMR_SHIFT 4 |
110 | #define STATUS2_DBCHG_SHIFT 5 | 124 | #define STATUS2_DBCHG_SHIFT 5 |
111 | #define STATUS2_VBVOLT_SHIFT 6 | 125 | #define STATUS2_VBVOLT_SHIFT 6 |
126 | #define MAX77836_STATUS2_VIDRM_SHIFT 7 | ||
112 | #define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT) | 127 | #define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT) |
113 | #define STATUS2_CHGDETRUN_MASK (0x1 << STATUS2_CHGDETRUN_SHIFT) | 128 | #define STATUS2_CHGDETRUN_MASK BIT(STATUS2_CHGDETRUN_SHIFT) |
114 | #define STATUS2_DCDTMR_MASK (0x1 << STATUS2_DCDTMR_SHIFT) | 129 | #define STATUS2_DCDTMR_MASK BIT(STATUS2_DCDTMR_SHIFT) |
115 | #define STATUS2_DBCHG_MASK (0x1 << STATUS2_DBCHG_SHIFT) | 130 | #define STATUS2_DBCHG_MASK BIT(STATUS2_DBCHG_SHIFT) |
116 | #define STATUS2_VBVOLT_MASK (0x1 << STATUS2_VBVOLT_SHIFT) | 131 | #define STATUS2_VBVOLT_MASK BIT(STATUS2_VBVOLT_SHIFT) |
132 | #define MAX77836_STATUS2_VIDRM_MASK BIT(MAX77836_STATUS2_VIDRM_SHIFT) | ||
117 | 133 | ||
118 | /* MAX14577 CONTROL1 register */ | 134 | /* MAX14577 CONTROL1 register */ |
119 | #define COMN1SW_SHIFT 0 | 135 | #define COMN1SW_SHIFT 0 |
@@ -122,8 +138,8 @@ enum max14577_muic_charger_type { | |||
122 | #define IDBEN_SHIFT 7 | 138 | #define IDBEN_SHIFT 7 |
123 | #define COMN1SW_MASK (0x7 << COMN1SW_SHIFT) | 139 | #define COMN1SW_MASK (0x7 << COMN1SW_SHIFT) |
124 | #define COMP2SW_MASK (0x7 << COMP2SW_SHIFT) | 140 | #define COMP2SW_MASK (0x7 << COMP2SW_SHIFT) |
125 | #define MICEN_MASK (0x1 << MICEN_SHIFT) | 141 | #define MICEN_MASK BIT(MICEN_SHIFT) |
126 | #define IDBEN_MASK (0x1 << IDBEN_SHIFT) | 142 | #define IDBEN_MASK BIT(IDBEN_SHIFT) |
127 | #define CLEAR_IDBEN_MICEN_MASK (COMN1SW_MASK | COMP2SW_MASK) | 143 | #define CLEAR_IDBEN_MICEN_MASK (COMN1SW_MASK | COMP2SW_MASK) |
128 | #define CTRL1_SW_USB ((1 << COMP2SW_SHIFT) \ | 144 | #define CTRL1_SW_USB ((1 << COMP2SW_SHIFT) \ |
129 | | (1 << COMN1SW_SHIFT)) | 145 | | (1 << COMN1SW_SHIFT)) |
@@ -143,14 +159,14 @@ enum max14577_muic_charger_type { | |||
143 | #define CTRL2_ACCDET_SHIFT (5) | 159 | #define CTRL2_ACCDET_SHIFT (5) |
144 | #define CTRL2_USBCPINT_SHIFT (6) | 160 | #define CTRL2_USBCPINT_SHIFT (6) |
145 | #define CTRL2_RCPS_SHIFT (7) | 161 | #define CTRL2_RCPS_SHIFT (7) |
146 | #define CTRL2_LOWPWR_MASK (0x1 << CTRL2_LOWPWR_SHIFT) | 162 | #define CTRL2_LOWPWR_MASK BIT(CTRL2_LOWPWR_SHIFT) |
147 | #define CTRL2_ADCEN_MASK (0x1 << CTRL2_ADCEN_SHIFT) | 163 | #define CTRL2_ADCEN_MASK BIT(CTRL2_ADCEN_SHIFT) |
148 | #define CTRL2_CPEN_MASK (0x1 << CTRL2_CPEN_SHIFT) | 164 | #define CTRL2_CPEN_MASK BIT(CTRL2_CPEN_SHIFT) |
149 | #define CTRL2_SFOUTASRT_MASK (0x1 << CTRL2_SFOUTASRT_SHIFT) | 165 | #define CTRL2_SFOUTASRT_MASK BIT(CTRL2_SFOUTASRT_SHIFT) |
150 | #define CTRL2_SFOUTORD_MASK (0x1 << CTRL2_SFOUTORD_SHIFT) | 166 | #define CTRL2_SFOUTORD_MASK BIT(CTRL2_SFOUTORD_SHIFT) |
151 | #define CTRL2_ACCDET_MASK (0x1 << CTRL2_ACCDET_SHIFT) | 167 | #define CTRL2_ACCDET_MASK BIT(CTRL2_ACCDET_SHIFT) |
152 | #define CTRL2_USBCPINT_MASK (0x1 << CTRL2_USBCPINT_SHIFT) | 168 | #define CTRL2_USBCPINT_MASK BIT(CTRL2_USBCPINT_SHIFT) |
153 | #define CTRL2_RCPS_MASK (0x1 << CTR2_RCPS_SHIFT) | 169 | #define CTRL2_RCPS_MASK BIT(CTRL2_RCPS_SHIFT) |
154 | 170 | ||
155 | #define CTRL2_CPEN1_LOWPWR0 ((1 << CTRL2_CPEN_SHIFT) | \ | 171 | #define CTRL2_CPEN1_LOWPWR0 ((1 << CTRL2_CPEN_SHIFT) | \ |
156 | (0 << CTRL2_LOWPWR_SHIFT)) | 172 | (0 << CTRL2_LOWPWR_SHIFT)) |
@@ -198,14 +214,14 @@ enum max14577_charger_reg { | |||
198 | #define CDETCTRL1_DBEXIT_SHIFT 5 | 214 | #define CDETCTRL1_DBEXIT_SHIFT 5 |
199 | #define CDETCTRL1_DBIDLE_SHIFT 6 | 215 | #define CDETCTRL1_DBIDLE_SHIFT 6 |
200 | #define CDETCTRL1_CDPDET_SHIFT 7 | 216 | #define CDETCTRL1_CDPDET_SHIFT 7 |
201 | #define CDETCTRL1_CHGDETEN_MASK (0x1 << CDETCTRL1_CHGDETEN_SHIFT) | 217 | #define CDETCTRL1_CHGDETEN_MASK BIT(CDETCTRL1_CHGDETEN_SHIFT) |
202 | #define CDETCTRL1_CHGTYPMAN_MASK (0x1 << CDETCTRL1_CHGTYPMAN_SHIFT) | 218 | #define CDETCTRL1_CHGTYPMAN_MASK BIT(CDETCTRL1_CHGTYPMAN_SHIFT) |
203 | #define CDETCTRL1_DCDEN_MASK (0x1 << CDETCTRL1_DCDEN_SHIFT) | 219 | #define CDETCTRL1_DCDEN_MASK BIT(CDETCTRL1_DCDEN_SHIFT) |
204 | #define CDETCTRL1_DCD2SCT_MASK (0x1 << CDETCTRL1_DCD2SCT_SHIFT) | 220 | #define CDETCTRL1_DCD2SCT_MASK BIT(CDETCTRL1_DCD2SCT_SHIFT) |
205 | #define CDETCTRL1_DCHKTM_MASK (0x1 << CDETCTRL1_DCHKTM_SHIFT) | 221 | #define CDETCTRL1_DCHKTM_MASK BIT(CDETCTRL1_DCHKTM_SHIFT) |
206 | #define CDETCTRL1_DBEXIT_MASK (0x1 << CDETCTRL1_DBEXIT_SHIFT) | 222 | #define CDETCTRL1_DBEXIT_MASK BIT(CDETCTRL1_DBEXIT_SHIFT) |
207 | #define CDETCTRL1_DBIDLE_MASK (0x1 << CDETCTRL1_DBIDLE_SHIFT) | 223 | #define CDETCTRL1_DBIDLE_MASK BIT(CDETCTRL1_DBIDLE_SHIFT) |
208 | #define CDETCTRL1_CDPDET_MASK (0x1 << CDETCTRL1_CDPDET_SHIFT) | 224 | #define CDETCTRL1_CDPDET_MASK BIT(CDETCTRL1_CDPDET_SHIFT) |
209 | 225 | ||
210 | /* MAX14577 CHGCTRL1 register */ | 226 | /* MAX14577 CHGCTRL1 register */ |
211 | #define CHGCTRL1_TCHW_SHIFT 4 | 227 | #define CHGCTRL1_TCHW_SHIFT 4 |
@@ -213,9 +229,9 @@ enum max14577_charger_reg { | |||
213 | 229 | ||
214 | /* MAX14577 CHGCTRL2 register */ | 230 | /* MAX14577 CHGCTRL2 register */ |
215 | #define CHGCTRL2_MBCHOSTEN_SHIFT 6 | 231 | #define CHGCTRL2_MBCHOSTEN_SHIFT 6 |
216 | #define CHGCTRL2_MBCHOSTEN_MASK (0x1 << CHGCTRL2_MBCHOSTEN_SHIFT) | 232 | #define CHGCTRL2_MBCHOSTEN_MASK BIT(CHGCTRL2_MBCHOSTEN_SHIFT) |
217 | #define CHGCTRL2_VCHGR_RC_SHIFT 7 | 233 | #define CHGCTRL2_VCHGR_RC_SHIFT 7 |
218 | #define CHGCTRL2_VCHGR_RC_MASK (0x1 << CHGCTRL2_VCHGR_RC_SHIFT) | 234 | #define CHGCTRL2_VCHGR_RC_MASK BIT(CHGCTRL2_VCHGR_RC_SHIFT) |
219 | 235 | ||
220 | /* MAX14577 CHGCTRL3 register */ | 236 | /* MAX14577 CHGCTRL3 register */ |
221 | #define CHGCTRL3_MBCCVWRC_SHIFT 0 | 237 | #define CHGCTRL3_MBCCVWRC_SHIFT 0 |
@@ -225,7 +241,7 @@ enum max14577_charger_reg { | |||
225 | #define CHGCTRL4_MBCICHWRCH_SHIFT 0 | 241 | #define CHGCTRL4_MBCICHWRCH_SHIFT 0 |
226 | #define CHGCTRL4_MBCICHWRCH_MASK (0xf << CHGCTRL4_MBCICHWRCH_SHIFT) | 242 | #define CHGCTRL4_MBCICHWRCH_MASK (0xf << CHGCTRL4_MBCICHWRCH_SHIFT) |
227 | #define CHGCTRL4_MBCICHWRCL_SHIFT 4 | 243 | #define CHGCTRL4_MBCICHWRCL_SHIFT 4 |
228 | #define CHGCTRL4_MBCICHWRCL_MASK (0x1 << CHGCTRL4_MBCICHWRCL_SHIFT) | 244 | #define CHGCTRL4_MBCICHWRCL_MASK BIT(CHGCTRL4_MBCICHWRCL_SHIFT) |
229 | 245 | ||
230 | /* MAX14577 CHGCTRL5 register */ | 246 | /* MAX14577 CHGCTRL5 register */ |
231 | #define CHGCTRL5_EOCS_SHIFT 0 | 247 | #define CHGCTRL5_EOCS_SHIFT 0 |
@@ -233,7 +249,7 @@ enum max14577_charger_reg { | |||
233 | 249 | ||
234 | /* MAX14577 CHGCTRL6 register */ | 250 | /* MAX14577 CHGCTRL6 register */ |
235 | #define CHGCTRL6_AUTOSTOP_SHIFT 5 | 251 | #define CHGCTRL6_AUTOSTOP_SHIFT 5 |
236 | #define CHGCTRL6_AUTOSTOP_MASK (0x1 << CHGCTRL6_AUTOSTOP_SHIFT) | 252 | #define CHGCTRL6_AUTOSTOP_MASK BIT(CHGCTRL6_AUTOSTOP_SHIFT) |
237 | 253 | ||
238 | /* MAX14577 CHGCTRL7 register */ | 254 | /* MAX14577 CHGCTRL7 register */ |
239 | #define CHGCTRL7_OTPCGHCVS_SHIFT 0 | 255 | #define CHGCTRL7_OTPCGHCVS_SHIFT 0 |
@@ -245,14 +261,111 @@ enum max14577_charger_reg { | |||
245 | #define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP 50000 | 261 | #define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP 50000 |
246 | #define MAX14577_REGULATOR_CURRENT_LIMIT_MAX 950000 | 262 | #define MAX14577_REGULATOR_CURRENT_LIMIT_MAX 950000 |
247 | 263 | ||
264 | /* MAX77836 regulator current limits (as in CHGCTRL4 register), uA */ | ||
265 | #define MAX77836_REGULATOR_CURRENT_LIMIT_MIN 45000 | ||
266 | #define MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_START 100000 | ||
267 | #define MAX77836_REGULATOR_CURRENT_LIMIT_HIGH_STEP 25000 | ||
268 | #define MAX77836_REGULATOR_CURRENT_LIMIT_MAX 475000 | ||
269 | |||
248 | /* MAX14577 regulator SFOUT LDO voltage, fixed, uV */ | 270 | /* MAX14577 regulator SFOUT LDO voltage, fixed, uV */ |
249 | #define MAX14577_REGULATOR_SAFEOUT_VOLTAGE 4900000 | 271 | #define MAX14577_REGULATOR_SAFEOUT_VOLTAGE 4900000 |
250 | 272 | ||
273 | /* MAX77836 regulator LDOx voltage, uV */ | ||
274 | #define MAX77836_REGULATOR_LDO_VOLTAGE_MIN 800000 | ||
275 | #define MAX77836_REGULATOR_LDO_VOLTAGE_MAX 3950000 | ||
276 | #define MAX77836_REGULATOR_LDO_VOLTAGE_STEP 50000 | ||
277 | #define MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM 64 | ||
278 | |||
279 | /* Slave addr = 0x46: PMIC */ | ||
280 | enum max77836_pmic_reg { | ||
281 | MAX77836_PMIC_REG_PMIC_ID = 0x20, | ||
282 | MAX77836_PMIC_REG_PMIC_REV = 0x21, | ||
283 | MAX77836_PMIC_REG_INTSRC = 0x22, | ||
284 | MAX77836_PMIC_REG_INTSRC_MASK = 0x23, | ||
285 | MAX77836_PMIC_REG_TOPSYS_INT = 0x24, | ||
286 | MAX77836_PMIC_REG_TOPSYS_INT_MASK = 0x26, | ||
287 | MAX77836_PMIC_REG_TOPSYS_STAT = 0x28, | ||
288 | MAX77836_PMIC_REG_MRSTB_CNTL = 0x2A, | ||
289 | MAX77836_PMIC_REG_LSCNFG = 0x2B, | ||
290 | |||
291 | MAX77836_LDO_REG_CNFG1_LDO1 = 0x51, | ||
292 | MAX77836_LDO_REG_CNFG2_LDO1 = 0x52, | ||
293 | MAX77836_LDO_REG_CNFG1_LDO2 = 0x53, | ||
294 | MAX77836_LDO_REG_CNFG2_LDO2 = 0x54, | ||
295 | MAX77836_LDO_REG_CNFG_LDO_BIAS = 0x55, | ||
296 | |||
297 | MAX77836_COMP_REG_COMP1 = 0x60, | ||
298 | |||
299 | MAX77836_PMIC_REG_END, | ||
300 | }; | ||
301 | |||
302 | #define MAX77836_INTSRC_MASK_TOP_INT_SHIFT 1 | ||
303 | #define MAX77836_INTSRC_MASK_MUIC_CHG_INT_SHIFT 3 | ||
304 | #define MAX77836_INTSRC_MASK_TOP_INT_MASK BIT(MAX77836_INTSRC_MASK_TOP_INT_SHIFT) | ||
305 | #define MAX77836_INTSRC_MASK_MUIC_CHG_INT_MASK BIT(MAX77836_INTSRC_MASK_MUIC_CHG_INT_SHIFT) | ||
306 | |||
307 | /* MAX77836 PMIC interrupts */ | ||
308 | #define MAX77836_TOPSYS_INT_T120C_SHIFT 0 | ||
309 | #define MAX77836_TOPSYS_INT_T140C_SHIFT 1 | ||
310 | #define MAX77836_TOPSYS_INT_T120C_MASK BIT(MAX77836_TOPSYS_INT_T120C_SHIFT) | ||
311 | #define MAX77836_TOPSYS_INT_T140C_MASK BIT(MAX77836_TOPSYS_INT_T140C_SHIFT) | ||
312 | |||
313 | /* LDO1/LDO2 CONFIG1 register */ | ||
314 | #define MAX77836_CNFG1_LDO_PWRMD_SHIFT 6 | ||
315 | #define MAX77836_CNFG1_LDO_TV_SHIFT 0 | ||
316 | #define MAX77836_CNFG1_LDO_PWRMD_MASK (0x3 << MAX77836_CNFG1_LDO_PWRMD_SHIFT) | ||
317 | #define MAX77836_CNFG1_LDO_TV_MASK (0x3f << MAX77836_CNFG1_LDO_TV_SHIFT) | ||
318 | |||
319 | /* LDO1/LDO2 CONFIG2 register */ | ||
320 | #define MAX77836_CNFG2_LDO_OVCLMPEN_SHIFT 7 | ||
321 | #define MAX77836_CNFG2_LDO_ALPMEN_SHIFT 6 | ||
322 | #define MAX77836_CNFG2_LDO_COMP_SHIFT 4 | ||
323 | #define MAX77836_CNFG2_LDO_POK_SHIFT 3 | ||
324 | #define MAX77836_CNFG2_LDO_ADE_SHIFT 1 | ||
325 | #define MAX77836_CNFG2_LDO_SS_SHIFT 0 | ||
326 | #define MAX77836_CNFG2_LDO_OVCLMPEN_MASK BIT(MAX77836_CNFG2_LDO_OVCLMPEN_SHIFT) | ||
327 | #define MAX77836_CNFG2_LDO_ALPMEN_MASK BIT(MAX77836_CNFG2_LDO_ALPMEN_SHIFT) | ||
328 | #define MAX77836_CNFG2_LDO_COMP_MASK (0x3 << MAX77836_CNFG2_LDO_COMP_SHIFT) | ||
329 | #define MAX77836_CNFG2_LDO_POK_MASK BIT(MAX77836_CNFG2_LDO_POK_SHIFT) | ||
330 | #define MAX77836_CNFG2_LDO_ADE_MASK BIT(MAX77836_CNFG2_LDO_ADE_SHIFT) | ||
331 | #define MAX77836_CNFG2_LDO_SS_MASK BIT(MAX77836_CNFG2_LDO_SS_SHIFT) | ||
332 | |||
333 | /* Slave addr = 0x6C: Fuel-Gauge/Battery */ | ||
334 | enum max77836_fg_reg { | ||
335 | MAX77836_FG_REG_VCELL_MSB = 0x02, | ||
336 | MAX77836_FG_REG_VCELL_LSB = 0x03, | ||
337 | MAX77836_FG_REG_SOC_MSB = 0x04, | ||
338 | MAX77836_FG_REG_SOC_LSB = 0x05, | ||
339 | MAX77836_FG_REG_MODE_H = 0x06, | ||
340 | MAX77836_FG_REG_MODE_L = 0x07, | ||
341 | MAX77836_FG_REG_VERSION_MSB = 0x08, | ||
342 | MAX77836_FG_REG_VERSION_LSB = 0x09, | ||
343 | MAX77836_FG_REG_HIBRT_H = 0x0A, | ||
344 | MAX77836_FG_REG_HIBRT_L = 0x0B, | ||
345 | MAX77836_FG_REG_CONFIG_H = 0x0C, | ||
346 | MAX77836_FG_REG_CONFIG_L = 0x0D, | ||
347 | MAX77836_FG_REG_VALRT_MIN = 0x14, | ||
348 | MAX77836_FG_REG_VALRT_MAX = 0x15, | ||
349 | MAX77836_FG_REG_CRATE_MSB = 0x16, | ||
350 | MAX77836_FG_REG_CRATE_LSB = 0x17, | ||
351 | MAX77836_FG_REG_VRESET = 0x18, | ||
352 | MAX77836_FG_REG_FGID = 0x19, | ||
353 | MAX77836_FG_REG_STATUS_H = 0x1A, | ||
354 | MAX77836_FG_REG_STATUS_L = 0x1B, | ||
355 | /* | ||
356 | * TODO: TABLE registers | ||
357 | * TODO: CMD register | ||
358 | */ | ||
359 | |||
360 | MAX77836_FG_REG_END, | ||
361 | }; | ||
362 | |||
251 | enum max14577_irq { | 363 | enum max14577_irq { |
252 | /* INT1 */ | 364 | /* INT1 */ |
253 | MAX14577_IRQ_INT1_ADC, | 365 | MAX14577_IRQ_INT1_ADC, |
254 | MAX14577_IRQ_INT1_ADCLOW, | 366 | MAX14577_IRQ_INT1_ADCLOW, |
255 | MAX14577_IRQ_INT1_ADCERR, | 367 | MAX14577_IRQ_INT1_ADCERR, |
368 | MAX77836_IRQ_INT1_ADC1K, | ||
256 | 369 | ||
257 | /* INT2 */ | 370 | /* INT2 */ |
258 | MAX14577_IRQ_INT2_CHGTYP, | 371 | MAX14577_IRQ_INT2_CHGTYP, |
@@ -260,6 +373,7 @@ enum max14577_irq { | |||
260 | MAX14577_IRQ_INT2_DCDTMR, | 373 | MAX14577_IRQ_INT2_DCDTMR, |
261 | MAX14577_IRQ_INT2_DBCHG, | 374 | MAX14577_IRQ_INT2_DBCHG, |
262 | MAX14577_IRQ_INT2_VBVOLT, | 375 | MAX14577_IRQ_INT2_VBVOLT, |
376 | MAX77836_IRQ_INT2_VIDRM, | ||
263 | 377 | ||
264 | /* INT3 */ | 378 | /* INT3 */ |
265 | MAX14577_IRQ_INT3_EOC, | 379 | MAX14577_IRQ_INT3_EOC, |
@@ -267,21 +381,25 @@ enum max14577_irq { | |||
267 | MAX14577_IRQ_INT3_OVP, | 381 | MAX14577_IRQ_INT3_OVP, |
268 | MAX14577_IRQ_INT3_MBCCHGERR, | 382 | MAX14577_IRQ_INT3_MBCCHGERR, |
269 | 383 | ||
384 | /* TOPSYS_INT, only MAX77836 */ | ||
385 | MAX77836_IRQ_TOPSYS_T140C, | ||
386 | MAX77836_IRQ_TOPSYS_T120C, | ||
387 | |||
270 | MAX14577_IRQ_NUM, | 388 | MAX14577_IRQ_NUM, |
271 | }; | 389 | }; |
272 | 390 | ||
273 | struct max14577 { | 391 | struct max14577 { |
274 | struct device *dev; | 392 | struct device *dev; |
275 | struct i2c_client *i2c; /* Slave addr = 0x4A */ | 393 | struct i2c_client *i2c; /* Slave addr = 0x4A */ |
394 | struct i2c_client *i2c_pmic; /* Slave addr = 0x46 */ | ||
395 | enum maxim_device_type dev_type; | ||
276 | 396 | ||
277 | struct regmap *regmap; | 397 | struct regmap *regmap; /* For MUIC and Charger */ |
398 | struct regmap *regmap_pmic; | ||
278 | 399 | ||
279 | struct regmap_irq_chip_data *irq_data; | 400 | struct regmap_irq_chip_data *irq_data; /* For MUIC and Charger */ |
401 | struct regmap_irq_chip_data *irq_data_pmic; | ||
280 | int irq; | 402 | int irq; |
281 | |||
282 | /* Device ID */ | ||
283 | u8 vendor_id; /* Vendor Identification */ | ||
284 | u8 device_id; /* Chip Version */ | ||
285 | }; | 403 | }; |
286 | 404 | ||
287 | /* MAX14577 shared regmap API function */ | 405 | /* MAX14577 shared regmap API function */ |
diff --git a/include/linux/mfd/max14577.h b/include/linux/mfd/max14577.h index 736d39c3ec0d..c83fbed1c7b6 100644 --- a/include/linux/mfd/max14577.h +++ b/include/linux/mfd/max14577.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * max14577.h - Driver for the Maxim 14577 | 2 | * max14577.h - Driver for the Maxim 14577/77836 |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> |
7 | * | 7 | * |
@@ -20,6 +20,9 @@ | |||
20 | * MAX14577 has MUIC, Charger devices. | 20 | * MAX14577 has MUIC, Charger devices. |
21 | * The devices share the same I2C bus and interrupt line | 21 | * The devices share the same I2C bus and interrupt line |
22 | * included in this mfd driver. | 22 | * included in this mfd driver. |
23 | * | ||
24 | * MAX77836 has additional PMIC and Fuel-Gauge on different I2C slave | ||
25 | * addresses. | ||
23 | */ | 26 | */ |
24 | 27 | ||
25 | #ifndef __MAX14577_H__ | 28 | #ifndef __MAX14577_H__ |
@@ -32,7 +35,17 @@ enum max14577_regulators { | |||
32 | MAX14577_SAFEOUT = 0, | 35 | MAX14577_SAFEOUT = 0, |
33 | MAX14577_CHARGER, | 36 | MAX14577_CHARGER, |
34 | 37 | ||
35 | MAX14577_REG_MAX, | 38 | MAX14577_REGULATOR_NUM, |
39 | }; | ||
40 | |||
41 | /* MAX77836 regulator IDs */ | ||
42 | enum max77836_regulators { | ||
43 | MAX77836_SAFEOUT = 0, | ||
44 | MAX77836_CHARGER, | ||
45 | MAX77836_LDO1, | ||
46 | MAX77836_LDO2, | ||
47 | |||
48 | MAX77836_REGULATOR_NUM, | ||
36 | }; | 49 | }; |
37 | 50 | ||
38 | struct max14577_regulator_platform_data { | 51 | struct max14577_regulator_platform_data { |
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index 48395a69a7e9..575a86c7fcbd 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/mutex.h> | 11 | #include <linux/mutex.h> |
12 | 12 | ||
13 | struct device; | 13 | struct device; |
14 | struct regulator; | ||
14 | 15 | ||
15 | enum stmpe_block { | 16 | enum stmpe_block { |
16 | STMPE_BLOCK_GPIO = 1 << 0, | 17 | STMPE_BLOCK_GPIO = 1 << 0, |
@@ -62,6 +63,8 @@ struct stmpe_client_info; | |||
62 | 63 | ||
63 | /** | 64 | /** |
64 | * struct stmpe - STMPE MFD structure | 65 | * struct stmpe - STMPE MFD structure |
66 | * @vcc: optional VCC regulator | ||
67 | * @vio: optional VIO regulator | ||
65 | * @lock: lock protecting I/O operations | 68 | * @lock: lock protecting I/O operations |
66 | * @irq_lock: IRQ bus lock | 69 | * @irq_lock: IRQ bus lock |
67 | * @dev: device, mostly for dev_dbg() | 70 | * @dev: device, mostly for dev_dbg() |
@@ -73,13 +76,14 @@ struct stmpe_client_info; | |||
73 | * @regs: list of addresses of registers which are at different addresses on | 76 | * @regs: list of addresses of registers which are at different addresses on |
74 | * different variants. Indexed by one of STMPE_IDX_*. | 77 | * different variants. Indexed by one of STMPE_IDX_*. |
75 | * @irq: irq number for stmpe | 78 | * @irq: irq number for stmpe |
76 | * @irq_base: starting IRQ number for internal IRQs | ||
77 | * @num_gpios: number of gpios, differs for variants | 79 | * @num_gpios: number of gpios, differs for variants |
78 | * @ier: cache of IER registers for bus_lock | 80 | * @ier: cache of IER registers for bus_lock |
79 | * @oldier: cache of IER registers for bus_lock | 81 | * @oldier: cache of IER registers for bus_lock |
80 | * @pdata: platform data | 82 | * @pdata: platform data |
81 | */ | 83 | */ |
82 | struct stmpe { | 84 | struct stmpe { |
85 | struct regulator *vcc; | ||
86 | struct regulator *vio; | ||
83 | struct mutex lock; | 87 | struct mutex lock; |
84 | struct mutex irq_lock; | 88 | struct mutex irq_lock; |
85 | struct device *dev; | 89 | struct device *dev; |
@@ -91,7 +95,6 @@ struct stmpe { | |||
91 | const u8 *regs; | 95 | const u8 *regs; |
92 | 96 | ||
93 | int irq; | 97 | int irq; |
94 | int irq_base; | ||
95 | int num_gpios; | 98 | int num_gpios; |
96 | u8 ier[2]; | 99 | u8 ier[2]; |
97 | u8 oldier[2]; | 100 | u8 oldier[2]; |
@@ -132,8 +135,6 @@ struct stmpe_keypad_platform_data { | |||
132 | 135 | ||
133 | /** | 136 | /** |
134 | * struct stmpe_gpio_platform_data - STMPE GPIO platform data | 137 | * struct stmpe_gpio_platform_data - STMPE GPIO platform data |
135 | * @gpio_base: first gpio number assigned. A maximum of | ||
136 | * %STMPE_NR_GPIOS GPIOs will be allocated. | ||
137 | * @norequest_mask: bitmask specifying which GPIOs should _not_ be | 138 | * @norequest_mask: bitmask specifying which GPIOs should _not_ be |
138 | * requestable due to different usage (e.g. touch, keypad) | 139 | * requestable due to different usage (e.g. touch, keypad) |
139 | * STMPE_GPIO_NOREQ_* macros can be used here. | 140 | * STMPE_GPIO_NOREQ_* macros can be used here. |
@@ -141,7 +142,6 @@ struct stmpe_keypad_platform_data { | |||
141 | * @remove: board specific remove callback | 142 | * @remove: board specific remove callback |
142 | */ | 143 | */ |
143 | struct stmpe_gpio_platform_data { | 144 | struct stmpe_gpio_platform_data { |
144 | int gpio_base; | ||
145 | unsigned norequest_mask; | 145 | unsigned norequest_mask; |
146 | void (*setup)(struct stmpe *stmpe, unsigned gpio_base); | 146 | void (*setup)(struct stmpe *stmpe, unsigned gpio_base); |
147 | void (*remove)(struct stmpe *stmpe, unsigned gpio_base); | 147 | void (*remove)(struct stmpe *stmpe, unsigned gpio_base); |
@@ -195,8 +195,6 @@ struct stmpe_ts_platform_data { | |||
195 | * @irq_trigger: IRQ trigger to use for the interrupt to the host | 195 | * @irq_trigger: IRQ trigger to use for the interrupt to the host |
196 | * @autosleep: bool to enable/disable stmpe autosleep | 196 | * @autosleep: bool to enable/disable stmpe autosleep |
197 | * @autosleep_timeout: inactivity timeout in milliseconds for autosleep | 197 | * @autosleep_timeout: inactivity timeout in milliseconds for autosleep |
198 | * @irq_base: base IRQ number. %STMPE_NR_IRQS irqs will be used, or | ||
199 | * %STMPE_NR_INTERNAL_IRQS if the GPIO driver is not used. | ||
200 | * @irq_over_gpio: true if gpio is used to get irq | 198 | * @irq_over_gpio: true if gpio is used to get irq |
201 | * @irq_gpio: gpio number over which irq will be requested (significant only if | 199 | * @irq_gpio: gpio number over which irq will be requested (significant only if |
202 | * irq_over_gpio is true) | 200 | * irq_over_gpio is true) |
@@ -207,7 +205,6 @@ struct stmpe_ts_platform_data { | |||
207 | struct stmpe_platform_data { | 205 | struct stmpe_platform_data { |
208 | int id; | 206 | int id; |
209 | unsigned int blocks; | 207 | unsigned int blocks; |
210 | int irq_base; | ||
211 | unsigned int irq_trigger; | 208 | unsigned int irq_trigger; |
212 | bool autosleep; | 209 | bool autosleep; |
213 | bool irq_over_gpio; | 210 | bool irq_over_gpio; |
@@ -219,10 +216,4 @@ struct stmpe_platform_data { | |||
219 | struct stmpe_ts_platform_data *ts; | 216 | struct stmpe_ts_platform_data *ts; |
220 | }; | 217 | }; |
221 | 218 | ||
222 | #define STMPE_NR_INTERNAL_IRQS 9 | ||
223 | #define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x)) | ||
224 | |||
225 | #define STMPE_NR_GPIOS 24 | ||
226 | #define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS) | ||
227 | |||
228 | #endif | 219 | #endif |
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h index 3f43069413e7..45f0f9d2ed25 100644 --- a/include/linux/mfd/tps65090.h +++ b/include/linux/mfd/tps65090.h | |||
@@ -64,6 +64,20 @@ enum { | |||
64 | TPS65090_REGULATOR_MAX, | 64 | TPS65090_REGULATOR_MAX, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* Register addresses */ | ||
68 | #define TPS65090_REG_INTR_STS 0x00 | ||
69 | #define TPS65090_REG_INTR_STS2 0x01 | ||
70 | #define TPS65090_REG_INTR_MASK 0x02 | ||
71 | #define TPS65090_REG_INTR_MASK2 0x03 | ||
72 | #define TPS65090_REG_CG_CTRL0 0x04 | ||
73 | #define TPS65090_REG_CG_CTRL1 0x05 | ||
74 | #define TPS65090_REG_CG_CTRL2 0x06 | ||
75 | #define TPS65090_REG_CG_CTRL3 0x07 | ||
76 | #define TPS65090_REG_CG_CTRL4 0x08 | ||
77 | #define TPS65090_REG_CG_CTRL5 0x09 | ||
78 | #define TPS65090_REG_CG_STATUS1 0x0a | ||
79 | #define TPS65090_REG_CG_STATUS2 0x0b | ||
80 | |||
67 | struct tps65090 { | 81 | struct tps65090 { |
68 | struct device *dev; | 82 | struct device *dev; |
69 | struct regmap *rmap; | 83 | struct regmap *rmap; |
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index cbecec2e353a..96187ed9f9bb 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #define TPS658621A 0x15 | 17 | #define TPS658621A 0x15 |
18 | #define TPS658621CD 0x2c | 18 | #define TPS658621CD 0x2c |
19 | #define TPS658623 0x1b | 19 | #define TPS658623 0x1b |
20 | #define TPS658640 0x01 | ||
21 | #define TPS658640v2 0x02 | ||
20 | #define TPS658643 0x03 | 22 | #define TPS658643 0x03 |
21 | 23 | ||
22 | enum { | 24 | enum { |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 2c59b1fb69dc..a7118052f32a 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/of.h> | ||
25 | #include <linux/mfd/mc13xxx.h> | 26 | #include <linux/mfd/mc13xxx.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
@@ -750,6 +751,7 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
750 | { | 751 | { |
751 | struct mc13783_priv *priv; | 752 | struct mc13783_priv *priv; |
752 | struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data; | 753 | struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data; |
754 | struct device_node *np; | ||
753 | int ret; | 755 | int ret; |
754 | 756 | ||
755 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | 757 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
@@ -760,7 +762,17 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
760 | priv->adc_ssi_port = pdata->adc_ssi_port; | 762 | priv->adc_ssi_port = pdata->adc_ssi_port; |
761 | priv->dac_ssi_port = pdata->dac_ssi_port; | 763 | priv->dac_ssi_port = pdata->dac_ssi_port; |
762 | } else { | 764 | } else { |
763 | return -ENOSYS; | 765 | np = of_get_child_by_name(pdev->dev.parent->of_node, "codec"); |
766 | if (!np) | ||
767 | return -ENOSYS; | ||
768 | |||
769 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); | ||
770 | if (ret) | ||
771 | return ret; | ||
772 | |||
773 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); | ||
774 | if (ret) | ||
775 | return ret; | ||
764 | } | 776 | } |
765 | 777 | ||
766 | dev_set_drvdata(&pdev->dev, priv); | 778 | dev_set_drvdata(&pdev->dev, priv); |