aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-04-16 02:36:13 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-04-16 02:36:13 -0400
commit6a3395beb99d7ae882ddf701c6fa6005ad7edebf (patch)
treea892e23174978236e101b49dedae554b931a03a0 /arch
parentad95b78c9f735da11ff9ec760e9b038cd82aead6 (diff)
sh: sh7724: Add CMT clockevents support.
This enables support for the CMT clockevents driver on SH7724. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 65570ed69e6c..8b87ba8f26bb 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -230,7 +230,40 @@ static struct platform_device veu1_device = {
230 .num_resources = ARRAY_SIZE(veu1_resources), 230 .num_resources = ARRAY_SIZE(veu1_resources),
231}; 231};
232 232
233static struct sh_cmt_config cmt_platform_data = {
234 .name = "CMT",
235 .channel_offset = 0x60,
236 .timer_bit = 5,
237 .clk = "cmt0",
238 .clockevent_rating = 125,
239 .clocksource_rating = 200,
240};
241
242static struct resource cmt_resources[] = {
243 [0] = {
244 .name = "CMT",
245 .start = 0x044a0060,
246 .end = 0x044a006b,
247 .flags = IORESOURCE_MEM,
248 },
249 [1] = {
250 .start = 104,
251 .flags = IORESOURCE_IRQ,
252 },
253};
254
255static struct platform_device cmt_device = {
256 .name = "sh_cmt",
257 .id = 0,
258 .dev = {
259 .platform_data = &cmt_platform_data,
260 },
261 .resource = cmt_resources,
262 .num_resources = ARRAY_SIZE(cmt_resources),
263};
264
233static struct platform_device *sh7724_devices[] __initdata = { 265static struct platform_device *sh7724_devices[] __initdata = {
266 &cmt_device,
234 &sci_device, 267 &sci_device,
235 &rtc_device, 268 &rtc_device,
236 &iic0_device, 269 &iic0_device,
operty(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { int ret = 0; struct collie_bat *bat = container_of(psy, struct collie_bat, psy); if (bat->is_present && !bat->is_present(bat) && psp != POWER_SUPPLY_PROP_PRESENT) { return -ENODEV; } switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = bat->status; break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = bat->technology; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = collie_read_bat(bat); break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (bat->full_chrg == -1) val->intval = bat->bat_max; else val->intval = bat->full_chrg; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: val->intval = bat->bat_max; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = bat->bat_min; break; case POWER_SUPPLY_PROP_TEMP: val->intval = collie_read_temp(bat); break; case POWER_SUPPLY_PROP_PRESENT: val->intval = bat->is_present ? bat->is_present(bat) : 1; break; default: ret = -EINVAL; break; } return ret; } static void collie_bat_external_power_changed(struct power_supply *psy) { schedule_work(&bat_work); } static irqreturn_t collie_bat_gpio_isr(int irq, void *data) { pr_info("collie_bat_gpio irq\n"); schedule_work(&bat_work); return IRQ_HANDLED; } static void collie_bat_update(struct collie_bat *bat) { int old; struct power_supply *psy = &bat->psy; mutex_lock(&bat->work_lock); old = bat->status; if (bat->is_present && !bat->is_present(bat)) { printk(KERN_NOTICE "%s not present\n", psy->name); bat->status = POWER_SUPPLY_STATUS_UNKNOWN; bat->full_chrg = -1; } else if (power_supply_am_i_supplied(psy)) { if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) { gpio_set_value(bat->gpio_charge_on, 1); mdelay(15); } if (gpio_get_value(bat->gpio_full)) { if (old == POWER_SUPPLY_STATUS_CHARGING || bat->full_chrg == -1) bat->full_chrg = collie_read_bat(bat); gpio_set_value(bat->gpio_charge_on, 0); bat->status = POWER_SUPPLY_STATUS_FULL; } else { gpio_set_value(bat->gpio_charge_on, 1); bat->status = POWER_SUPPLY_STATUS_CHARGING; } } else { gpio_set_value(bat->gpio_charge_on, 0); bat->status = POWER_SUPPLY_STATUS_DISCHARGING; } if (old != bat->status) power_supply_changed(psy); mutex_unlock(&bat->work_lock); } static void collie_bat_work(struct work_struct *work) { collie_bat_update(&collie_bat_main); } static enum power_supply_property collie_bat_main_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TEMP, }; static enum power_supply_property collie_bat_bu_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_PRESENT, }; static struct collie_bat collie_bat_main = { .status = POWER_SUPPLY_STATUS_DISCHARGING, .full_chrg = -1, .psy = { .name = "main-battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = collie_bat_main_props, .num_properties = ARRAY_SIZE(collie_bat_main_props), .get_property = collie_bat_get_property, .external_power_changed = collie_bat_external_power_changed, .use_for_apm = 1, }, .gpio_full = COLLIE_GPIO_CO, .gpio_charge_on = COLLIE_GPIO_CHARGE_ON, .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, .gpio_bat = COLLIE_GPIO_MBAT_ON, .adc_bat = UCB_ADC_INP_AD1, .adc_bat_divider = 155, .bat_max = 4310000, .bat_min = 1551 * 1000000 / 414, .gpio_temp = COLLIE_GPIO_TMP_ON, .adc_temp = UCB_ADC_INP_AD0, .adc_temp_divider = 10000, }; static struct collie_bat collie_bat_bu = { .status = POWER_SUPPLY_STATUS_UNKNOWN, .full_chrg = -1, .psy = { .name = "backup-battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = collie_bat_bu_props, .num_properties = ARRAY_SIZE(collie_bat_bu_props), .get_property = collie_bat_get_property, .external_power_changed = collie_bat_external_power_changed, }, .gpio_full = -1, .gpio_charge_on = -1, .technology = POWER_SUPPLY_TECHNOLOGY_LiMn, .gpio_bat = COLLIE_GPIO_BBAT_ON, .adc_bat = UCB_ADC_INP_AD1, .adc_bat_divider = 155, .bat_max = 3000000, .bat_min = 1900000, .gpio_temp = -1, .adc_temp = -1, .adc_temp_divider = -1, }; static struct gpio collie_batt_gpios[] = { { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" }, { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" }, { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" }, { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" }, { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" }, { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" }, }; #ifdef CONFIG_PM static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state) { /* flush all pending status updates */ flush_work(&bat_work); return 0; } static int collie_bat_resume(struct ucb1x00_dev *dev) { /* things may have changed while we were away */ schedule_work(&bat_work); return 0; } #else #define collie_bat_suspend NULL #define collie_bat_resume NULL #endif static int collie_bat_probe(struct ucb1x00_dev *dev) { int ret; if (!machine_is_collie()) return -ENODEV; ucb = dev->ucb; ret = gpio_request_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); if (ret) return ret; mutex_init(&collie_bat_main.work_lock); INIT_WORK(&bat_work, collie_bat_work); ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy); if (ret) goto err_psy_reg_main; ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy); if (ret) goto err_psy_reg_bu; ret = request_irq(gpio_to_irq(COLLIE_GPIO_CO), collie_bat_gpio_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "main full", &collie_bat_main); if (!ret) { schedule_work(&bat_work); return 0; } power_supply_unregister(&collie_bat_bu.psy); err_psy_reg_bu: power_supply_unregister(&collie_bat_main.psy); err_psy_reg_main: /* see comment in collie_bat_remove */ cancel_work_sync(&bat_work); gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); return ret; } static void collie_bat_remove(struct ucb1x00_dev *dev) { free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); power_supply_unregister(&collie_bat_bu.psy); power_supply_unregister(&collie_bat_main.psy); /* * Now cancel the bat_work. We won't get any more schedules, * since all sources (isr and external_power_changed) are * unregistered now. */ cancel_work_sync(&bat_work); gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); } static struct ucb1x00_driver collie_bat_driver = { .add = collie_bat_probe, .remove = collie_bat_remove, .suspend = collie_bat_suspend, .resume = collie_bat_resume, }; static int __init collie_bat_init(void) { return ucb1x00_register_driver(&collie_bat_driver); } static void __exit collie_bat_exit(void) { ucb1x00_unregister_driver(&collie_bat_driver); } module_init(collie_bat_init); module_exit(collie_bat_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thomas Kunze"); MODULE_DESCRIPTION("Collie battery driver");