static void __init athena_evt_machine_init(void) { pm_power_off = athena_power_off; ak98_arch_reset = athena_reset; ak98_nand_device.dev.platform_data = &athena_evt_nand_info; i2c_register_board_info(0, ak98_ts_devices, ARRAY_SIZE(ak98_ts_devices)); i2c_register_board_info(0, ak98_sensor_devices, ARRAY_SIZE(ak98_sensor_devices)); i2c_register_board_info(0, ak98_aw9523_ext, ARRAY_SIZE(ak98_aw9523_ext)); ak_sensor_device.dev.platform_data = &sensor_info; ak98adc_ts_device.dev.platform_data = &ak98adc_ts_info; // set battery platform_data ak98_battery_power.dev.platform_data = &ak98_bat_info; ak98pwm_backlight_device.dev.platform_data = &ak98pwm_backlight_data; spidev_info.max_speed_hz = ak98_get_asic_clk()/2; //spi_register_board_info(&spidev_info, 1); spi_register_board_info(&ar7643_info, 1); ak98_spi1_device.dev.platform_data = &ak98_spi1_info; /* register platform devices */ platform_add_devices(athena_evt_platform_devices, ARRAY_SIZE(athena_evt_platform_devices)); /* Initialize L2 buffer */ ak98_l2_init(); }
static int ak98sdio_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data) { struct ak98_mci_host *host; struct mmc_host *mmc; unsigned long newclk; unsigned long flags; struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data; host = container_of(nb, struct ak98_mci_host, freq_transition); PKCLK("%s\n",__func__); PKCLK("%s(): in_interrupt()=%ld\n", __func__, in_interrupt()); PKCLK("ak98_get_asic_clk = %ld\n",ak98_get_asic_clk()); PKCLK("freqs->new_cpufreq.asic_clk = %d\n", freqs->new_cpufreq.asic_clk); mmc = host->mmc; newclk = freqs->new_cpufreq.asic_clk; if ((val == CPUFREQ_PRECHANGE && newclk > host->asic_clkrate) || (val == CPUFREQ_POSTCHANGE && newclk < host->asic_clkrate)) { if (mmc->ios.power_mode != MMC_POWER_OFF && mmc->ios.clock != 0) { PKCLK("%s(): preempt_count()=%d\n", __func__, preempt_count()); down(&host->freq_lock); spin_lock_irqsave(&mmc->lock, flags); host->asic_clkrate = newclk; PKCLK("AK98MCICLOCK1 = %d\n",readl(host->base + AK98MCICLOCK)); ak98sdio_set_clk(host, &mmc->ios); PKCLK("AK98MCICLOCK2 = %d\n",readl(host->base + AK98MCICLOCK)); spin_unlock_irqrestore(&mmc->lock, flags); up(&host->freq_lock); } } return NOTIFY_DONE; }
static int __devinit ak98_sdio_probe(struct platform_device *pdev) { struct ak98_mci_platform_data *plat = pdev->dev.platform_data; struct ak98_mci_host *host; struct mmc_host *mmc; struct resource *res; int irq; int ret; /* must have platform data */ if (!plat) { ret = -EINVAL; goto out; } PK("%s\n", __func__); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); PK("res: %x, %u", res->start, resource_size(res)); res = request_mem_region(res->start, resource_size(res), DRIVER_NAME); if (!res) { ret = -EBUSY; goto out; } PK("res: %x, %u\n", res->start, resource_size(res)); mmc = mmc_alloc_host(sizeof(struct ak98_mci_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; goto out; } host = mmc_priv(mmc); host->mmc = mmc; host->gpio_wp = -ENOSYS; host->gpio_cd = -ENOSYS; ak98_sdio_reset(); host->clk = clk_get(&pdev->dev, "sdio_clk"); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); host->clk = NULL; goto host_free; } ret = clk_enable(host->clk); if (ret) goto clk_free; host->plat = plat; host->asic_clkrate = ak98_get_asic_clk(); host->base = ioremap(res->start, resource_size(res)); if (!host->base) { ret = -ENOMEM; goto clk_disable; } PK("asic_clkrate: %luhz,host->base=0x%x\n", host->asic_clkrate,host->base); mmc->ops = &ak98_mci_ops; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_4_BIT_DATA; #if 0 mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; #endif mmc->caps |= MMC_CAP_SDIO_IRQ; // mmc->caps |= MMC_CAP_NEEDS_POLL; mmc->f_min = host->asic_clkrate / (255+1 + 255+1); mmc->f_max = host->asic_clkrate / (0+1 + 0+1); mmc->f_max = mmc->f_max < fmax ? mmc->f_max : fmax; /* * We can do SGIO */ mmc->max_hw_segs = 16; mmc->max_phys_segs = NR_SG; /* * Since we only have a 16-bit data length register, we must * ensure that we don't exceed 2^16-1 bytes in a single request. */ mmc->max_req_size = 65535; /* * Set the maximum segment size. Since we aren't doing DMA * (yet) we are only limited by the data length register. */ mmc->max_seg_size = mmc->max_req_size; #if 0 /* * Block size can be up to 2048 bytes, but must be a power of two. */ mmc->max_blk_size = 2048; #else /* as l2 fifo limit to 512 bytes */ mmc->max_blk_size = 512; #endif /* * No limit on the number of blocks transferred. */ mmc->max_blk_count = mmc->max_req_size; spin_lock_init(&host->lock); ak98_group_config(ePIN_AS_SDIO); writel(MCI_ENABLE|MCI_FAIL_TRIGGER, host->base + AK98MCICLOCK); PK("%s: MCICLOCK: 0x%08x\n", __func__, readl(host->base + AK98MCICLOCK)); writel(0, host->base + AK98MCIMASK); PK("request irq %i\n", irq); ret = request_irq(irq, ak98_sdio_irq, IRQF_DISABLED, DRIVER_NAME " (cmd)", host); if (ret) goto unmap; host->irq_mci = irq; if(plat->gpio_cd >= 0) { host->gpio_cd = plat->gpio_cd; ak98_gpio_cfgpin(host->gpio_cd, AK98_GPIO_DIR_INPUT); ak98_gpio_pulldown(host->gpio_cd,AK98_PULLDOWN_DISABLE); ak98_gpio_pullup(host->gpio_cd, AK98_PULLUP_ENABLE); setup_timer(&host->detect_timer, ak98_sdio_detect_change, (unsigned long)host); irq = ak98_gpio_to_irq(host->gpio_cd); ret = request_irq(irq, ak98_sdio_card_detect_irq, IRQF_DISABLED, DRIVER_NAME " cd", host); printk("request gpio irq ret = %d, irq=%d", ret, irq); if (ret) goto irq_free; host->irq_cd = irq; host->irq_cd_type = IRQ_TYPE_LEVEL_LOW; } if(plat->gpio_wp >= 0) { host->gpio_wp = plat->gpio_wp; ak98_gpio_cfgpin(host->gpio_wp, AK98_GPIO_DIR_INPUT); ak98_gpio_pullup(host->gpio_wp, AK98_PULLUP_ENABLE); ak98_gpio_pulldown(host->gpio_wp,AK98_PULLDOWN_DISABLE); } platform_set_drvdata(pdev, mmc); ret = ak98sdio_cpufreq_register(host); if (ret) { goto irq_free; } ret = mmc_add_host(mmc); if (ret) { goto cpufreq_free; } PK(KERN_INFO "%s: ak98MCI at 0x%016llx irq %d\n", mmc_hostname(mmc), (unsigned long long)res->start, host->irq_mci); return 0; cpufreq_free: PK("ERR cpufreq_free\n"); ak98sdio_cpufreq_deregister(host); irq_free: PK("ERR irq_free\n"); free_irq(host->irq_mci, host); unmap: PK("ERR unmap\n"); iounmap(host->base); clk_disable: PK("ERR clk_disable\n"); clk_disable(host->clk); clk_free: PK("ERR clk_free\n"); clk_put(host->clk); host_free: PK("ERR host_free\n"); mmc_free_host(mmc); out: PK("ERR out\n"); return ret; }