Path: blob/master/drivers/mmc/host/sdhci-cns3xxx.c
15111 views
/*1* SDHCI support for CNS3xxx SoC2*3* Copyright 2008 Cavium Networks4* Copyright 2010 MontaVista Software, LLC.5*6* Authors: Scott Shu7* Anton Vorontsov <[email protected]>8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License version 2 as11* published by the Free Software Foundation.12*/1314#include <linux/delay.h>15#include <linux/device.h>16#include <linux/mmc/host.h>17#include <linux/mmc/sdhci-pltfm.h>18#include <mach/cns3xxx.h>19#include "sdhci.h"20#include "sdhci-pltfm.h"2122static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)23{24return 150000000;25}2627static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)28{29struct device *dev = mmc_dev(host->mmc);30int div = 1;31u16 clk;32unsigned long timeout;3334if (clock == host->clock)35return;3637sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);3839if (clock == 0)40goto out;4142while (host->max_clk / div > clock) {43/*44* On CNS3xxx divider grows linearly up to 4, and then45* exponentially up to 256.46*/47if (div < 4)48div += 1;49else if (div < 256)50div *= 2;51else52break;53}5455dev_dbg(dev, "desired SD clock: %d, actual: %d\n",56clock, host->max_clk / div);5758/* Divide by 3 is special. */59if (div != 3)60div >>= 1;6162clk = div << SDHCI_DIVIDER_SHIFT;63clk |= SDHCI_CLOCK_INT_EN;64sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);6566timeout = 20;67while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))68& SDHCI_CLOCK_INT_STABLE)) {69if (timeout == 0) {70dev_warn(dev, "clock is unstable");71break;72}73timeout--;74mdelay(1);75}7677clk |= SDHCI_CLOCK_CARD_EN;78sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);79out:80host->clock = clock;81}8283static struct sdhci_ops sdhci_cns3xxx_ops = {84.get_max_clock = sdhci_cns3xxx_get_max_clk,85.set_clock = sdhci_cns3xxx_set_clock,86};8788struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {89.ops = &sdhci_cns3xxx_ops,90.quirks = SDHCI_QUIRK_BROKEN_DMA |91SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |92SDHCI_QUIRK_INVERTED_WRITE_PROTECT |93SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |94SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |95SDHCI_QUIRK_NONSTANDARD_CLOCK,96};979899