gfs2: Simplify the seq file code for "sbstats"
[deliverable/linux.git] / drivers / spi / spi-pxa2xx.c
index e3223ac75a7c57d55e1c56e90dfac2aea877f8d5..7293d6d875c5c692184d1c45aea151f063bb6cd0 100644 (file)
@@ -60,21 +60,60 @@ MODULE_ALIAS("platform:pxa2xx-spi");
                                | QUARK_X1000_SSCR1_TFT         \
                                | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
 
-#define LPSS_RX_THRESH_DFLT    64
-#define LPSS_TX_LOTHRESH_DFLT  160
-#define LPSS_TX_HITHRESH_DFLT  224
-
-/* Offset from drv_data->lpss_base */
-#define GENERAL_REG            0x08
 #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
-#define SSP_REG                        0x0c
-#define SPI_CS_CONTROL         0x18
 #define SPI_CS_CONTROL_SW_MODE BIT(0)
 #define SPI_CS_CONTROL_CS_HIGH BIT(1)
 
+struct lpss_config {
+       /* LPSS offset from drv_data->ioaddr */
+       unsigned offset;
+       /* Register offsets from drv_data->lpss_base or -1 */
+       int reg_general;
+       int reg_ssp;
+       int reg_cs_ctrl;
+       /* FIFO thresholds */
+       u32 rx_threshold;
+       u32 tx_threshold_lo;
+       u32 tx_threshold_hi;
+};
+
+/* Keep these sorted with enum pxa_ssp_type */
+static const struct lpss_config lpss_platforms[] = {
+       {       /* LPSS_LPT_SSP */
+               .offset = 0x800,
+               .reg_general = 0x08,
+               .reg_ssp = 0x0c,
+               .reg_cs_ctrl = 0x18,
+               .rx_threshold = 64,
+               .tx_threshold_lo = 160,
+               .tx_threshold_hi = 224,
+       },
+       {       /* LPSS_BYT_SSP */
+               .offset = 0x400,
+               .reg_general = 0x08,
+               .reg_ssp = 0x0c,
+               .reg_cs_ctrl = 0x18,
+               .rx_threshold = 64,
+               .tx_threshold_lo = 160,
+               .tx_threshold_hi = 224,
+       },
+};
+
+static inline const struct lpss_config
+*lpss_get_config(const struct driver_data *drv_data)
+{
+       return &lpss_platforms[drv_data->ssp_type - LPSS_LPT_SSP];
+}
+
 static bool is_lpss_ssp(const struct driver_data *drv_data)
 {
-       return drv_data->ssp_type == LPSS_SSP;
+       switch (drv_data->ssp_type) {
+       case LPSS_LPT_SSP:
+       case LPSS_BYT_SSP:
+               return true;
+       default:
+               return false;
+       }
 }
 
 static bool is_quark_x1000_ssp(const struct driver_data *drv_data)
@@ -192,63 +231,43 @@ static void __lpss_ssp_write_priv(struct driver_data *drv_data,
  */
 static void lpss_ssp_setup(struct driver_data *drv_data)
 {
-       unsigned offset = 0x400;
-       u32 value, orig;
-
-       /*
-        * Perform auto-detection of the LPSS SSP private registers. They
-        * can be either at 1k or 2k offset from the base address.
-        */
-       orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-
-       /* Test SPI_CS_CONTROL_SW_MODE bit enabling */
-       value = orig | SPI_CS_CONTROL_SW_MODE;
-       writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       if (value != (orig | SPI_CS_CONTROL_SW_MODE)) {
-               offset = 0x800;
-               goto detection_done;
-       }
-
-       orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-
-       /* Test SPI_CS_CONTROL_SW_MODE bit disabling */
-       value = orig & ~SPI_CS_CONTROL_SW_MODE;
-       writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) {
-               offset = 0x800;
-               goto detection_done;
-       }
+       const struct lpss_config *config;
+       u32 value;
 
-detection_done:
-       /* Now set the LPSS base */
-       drv_data->lpss_base = drv_data->ioaddr + offset;
+       config = lpss_get_config(drv_data);
+       drv_data->lpss_base = drv_data->ioaddr + config->offset;
 
        /* Enable software chip select control */
        value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
-       __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
+       __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
 
        /* Enable multiblock DMA transfers */
        if (drv_data->master_info->enable_dma) {
-               __lpss_ssp_write_priv(drv_data, SSP_REG, 1);
-
-               value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
-               value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
-               __lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
+               __lpss_ssp_write_priv(drv_data, config->reg_ssp, 1);
+
+               if (config->reg_general >= 0) {
+                       value = __lpss_ssp_read_priv(drv_data,
+                                                    config->reg_general);
+                       value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+                       __lpss_ssp_write_priv(drv_data,
+                                             config->reg_general, value);
+               }
        }
 }
 
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
 {
+       const struct lpss_config *config;
        u32 value;
 
-       value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL);
+       config = lpss_get_config(drv_data);
+
+       value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
        if (enable)
                value &= ~SPI_CS_CONTROL_CS_HIGH;
        else
                value |= SPI_CS_CONTROL_CS_HIGH;
-       __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
+       __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
 }
 
 static void cs_assert(struct driver_data *drv_data)
@@ -1075,6 +1094,7 @@ static int setup(struct spi_device *spi)
 {
        struct pxa2xx_spi_chip *chip_info = NULL;
        struct chip_data *chip;
+       const struct lpss_config *config;
        struct driver_data *drv_data = spi_master_get_devdata(spi->master);
        unsigned int clk_div;
        uint tx_thres, tx_hi_thres, rx_thres;
@@ -1085,10 +1105,12 @@ static int setup(struct spi_device *spi)
                tx_hi_thres = 0;
                rx_thres = RX_THRESH_QUARK_X1000_DFLT;
                break;
-       case LPSS_SSP:
-               tx_thres = LPSS_TX_LOTHRESH_DFLT;
-               tx_hi_thres = LPSS_TX_HITHRESH_DFLT;
-               rx_thres = LPSS_RX_THRESH_DFLT;
+       case LPSS_LPT_SSP:
+       case LPSS_BYT_SSP:
+               config = lpss_get_config(drv_data);
+               tx_thres = config->tx_threshold_lo;
+               tx_hi_thres = config->tx_threshold_hi;
+               rx_thres = config->rx_threshold;
                break;
        default:
                tx_thres = TX_THRESH_DFLT;
@@ -1242,6 +1264,18 @@ static void cleanup(struct spi_device *spi)
 }
 
 #ifdef CONFIG_ACPI
+
+static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
+       { "INT33C0", LPSS_LPT_SSP },
+       { "INT33C1", LPSS_LPT_SSP },
+       { "INT3430", LPSS_LPT_SSP },
+       { "INT3431", LPSS_LPT_SSP },
+       { "80860F0E", LPSS_BYT_SSP },
+       { "8086228E", LPSS_BYT_SSP },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
+
 static struct pxa2xx_spi_master *
 pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 {
@@ -1249,12 +1283,19 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        struct acpi_device *adev;
        struct ssp_device *ssp;
        struct resource *res;
-       int devid;
+       const struct acpi_device_id *id;
+       int devid, type;
 
        if (!ACPI_HANDLE(&pdev->dev) ||
            acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
                return NULL;
 
+       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+       if (id)
+               type = (int)id->driver_data;
+       else
+               return NULL;
+
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return NULL;
@@ -1272,7 +1313,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 
        ssp->clk = devm_clk_get(&pdev->dev, NULL);
        ssp->irq = platform_get_irq(pdev, 0);
-       ssp->type = LPSS_SSP;
+       ssp->type = type;
        ssp->pdev = pdev;
 
        ssp->port_id = -1;
@@ -1285,16 +1326,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        return pdata;
 }
 
-static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
-       { "INT33C0", 0 },
-       { "INT33C1", 0 },
-       { "INT3430", 0 },
-       { "INT3431", 0 },
-       { "80860F0E", 0 },
-       { "8086228E", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
 #else
 static inline struct pxa2xx_spi_master *
 pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
This page took 0.027702 seconds and 5 git commands to generate.