All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] Added MC13892VK Power Management driver
@ 2010-03-16 16:18 Stefano Babic
  2010-03-20 23:55 ` Tom
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Stefano Babic @ 2010-03-16 16:18 UTC (permalink / raw)
  To: u-boot

Added SPI driver for the Power Management  Controller
used with i.MX51 Processor.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 drivers/misc/Makefile           |    1 +
 drivers/misc/mc13892_spi_pmic.c |  134 +++++++++++++++++++++++++++++++++++
 include/mc13892.h               |  149 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/mc13892_spi_pmic.c
 create mode 100644 include/mc13892.h

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f6df60f..5847262 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
 COBJS-$(CONFIG_NS87308) += ns87308.o
 COBJS-$(CONFIG_STATUS_LED) += status_led.o
 COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
+COBJS-$(CONFIG_MC13892_SPI_PMIC) += mc13892_spi_pmic.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/misc/mc13892_spi_pmic.c b/drivers/misc/mc13892_spi_pmic.c
new file mode 100644
index 0000000..f095fcc
--- /dev/null
+++ b/drivers/misc/mc13892_spi_pmic.c
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <linux/types.h>
+
+u32 mc13892_reg(struct spi_slave *slave, u32 reg, u32 val, u32 write)
+{
+	char tx[4];
+	char rx[4];
+	int i;
+	u32 tmp, pmic_tx, pmic_rx;
+
+	if (!slave)
+		return 0;
+
+	if (reg > 63 || write > 1) {
+		printf("<reg num> = %d is invalid. Should be less then 63\n",
+			reg);
+		return 0;
+	}
+	pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
+	debug("reg=0x%x, val=0x%08x\n", reg, pmic_tx);
+
+	tmp = pmic_tx;
+	for (i = 0; i < 4; i++) {
+		tx[i] = (tmp & 0xFF000000) >> 24;
+		tmp <<= 8;
+	}
+
+	if (spi_xfer(slave, 4 << 3, tx, rx,
+			SPI_XFER_BEGIN | SPI_XFER_END)) {
+		return -1;
+	}
+
+	if (write) {
+		tx[0] &= ~(1 << 31);
+		if (spi_xfer(slave, 4 << 3, tx, rx,
+			SPI_XFER_BEGIN | SPI_XFER_END)) {
+			return -1;
+		}
+	}
+
+	pmic_rx = (rx[0] << 24) | (rx[1] << 16) | (rx[2] << 8) | rx[3];
+	debug("reg=0x%x, val_read=0x%08x 0x%x 0x%x 0x%x 0x%x\n",
+		reg, pmic_rx, rx[0], rx[1], rx[2], rx[3]);
+	return pmic_rx;
+}
+
+void mc13892_show_pmic_info(struct spi_slave *slave)
+{
+	volatile u32 rev_id;
+
+	if (!slave)
+		return;
+
+	rev_id = mc13892_reg(slave, 7, 0, 0);
+	debug("PMIC ID: 0x%08x [Rev: ", rev_id);
+	switch (rev_id & 0x1F) {
+	case 0x1:
+		puts("1.0");
+		break;
+	case 0x9:
+		puts("1.1");
+		break;
+	case 0xA:
+		puts("1.2");
+		break;
+	case 0x10:
+		puts("2.0");
+		break;
+	case 0x11:
+		puts("2.1");
+		break;
+	case 0x18:
+		puts("3.0");
+		break;
+	case 0x19:
+		puts("3.1");
+		break;
+	case 0x1A:
+		puts("3.2");
+		break;
+	case 0x2:
+		puts("3.2A");
+		break;
+	case 0x1B:
+		puts("3.3");
+		break;
+	case 0x1D:
+		puts("3.5");
+		break;
+	default:
+		puts("unknown");
+		break;
+	}
+	puts("]\n");
+}
+
+struct spi_slave *mc13892_spi_probe(void)
+{
+	return spi_setup_slave(CONFIG_MC13892_SPI_PMIC_BUS,
+		CONFIG_MC13892_SPI_PMIC_CS,
+		CONFIG_MC13892_SPI_PMIC_CLK,
+		CONFIG_MC13892_SPI_PMIC_MODE);
+}
+
+void mc13892_spi_free(struct spi_slave *slave)
+{
+	if (slave)
+		spi_free_slave(slave);
+}
diff --git a/include/mc13892.h b/include/mc13892.h
new file mode 100644
index 0000000..b57e07b
--- /dev/null
+++ b/include/mc13892.h
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MC13892_H__
+#define __MC13892_H__
+
+enum {
+	MC13892_REG_INT_STATUS0 = 0,
+	MC13892_REG_INT_MASK0,
+	MC13892_REG_INT_SENSE0,
+	MC13892_REG_INT_STATUS1,
+	MC13892_REG_INT_MASK1,
+	MC13892_REG_INT_SENSE1,
+	MC13892_REG_PU_MODE_S,
+	MC13892_REG_IDENTIFICATION,
+	MC13892_REG_UNUSED0,
+	MC13892_REG_ACC0,
+	MC13892_REG_ACC1,		/*10 */
+	MC13892_REG_UNUSED1,
+	MC13892_REG_UNUSED2,
+	MC13892_REG_POWER_CTL0,
+	MC13892_REG_POWER_CTL1,
+	MC13892_REG_POWER_CTL2,
+	MC13892_REG_REGEN_ASSIGN,
+	MC13892_REG_UNUSED3,
+	MC13892_REG_MEM_A,
+	MC13892_REG_MEM_B,
+	MC13892_REG_RTC_TIME,		/*20 */
+	MC13892_REG_RTC_ALARM,
+	MC13892_REG_RTC_DAY,
+	MC13892_REG_RTC_DAY_ALARM,
+	MC13892_REG_SW_0,
+	MC13892_REG_SW_1,
+	MC13892_REG_SW_2,
+	MC13892_REG_SW_3,
+	MC13892_REG_SW_4,
+	MC13892_REG_SW_5,
+	MC13892_REG_SETTING_0,		/*30 */
+	MC13892_REG_SETTING_1,
+	MC13892_REG_MODE_0,
+	MC13892_REG_MODE_1,
+	MC13892_REG_POWER_MISC,
+	MC13892_REG_UNUSED4,
+	MC13892_REG_UNUSED5,
+	MC13892_REG_UNUSED6,
+	MC13892_REG_UNUSED7,
+	MC13892_REG_UNUSED8,
+	MC13892_REG_UNUSED9,		/*40 */
+	MC13892_REG_UNUSED10,
+	MC13892_REG_UNUSED11,
+	MC13892_REG_ADC0,
+	MC13892_REG_ADC1,
+	MC13892_REG_ADC2,
+	MC13892_REG_ADC3,
+	MC13892_REG_ADC4,
+	MC13892_REG_CHARGE,
+	MC13892_REG_USB0,
+	MC13892_REG_USB1,		/*50 */
+	MC13892_REG_LED_CTL0,
+	MC13892_REG_LED_CTL1,
+	MC13892_REG_LED_CTL2,
+	MC13892_REG_LED_CTL3,
+	MC13892_REG_UNUSED12,
+	MC13892_REG_UNUSED13,
+	MC13892_REG_TRIM0,
+	MC13892_REG_TRIM1,
+	MC13892_REG_TEST0,
+	MC13892_REG_TEST1,		/*60 */
+	MC13892_REG_TEST2,
+	MC13892_REG_TEST3,
+	MC13892_REG_TEST4,
+};
+
+/* MC13892_REG_POWER_MISC */
+
+#define PWGT1SPIEN	(1 << 15)
+#define PWGT2SPIEN	(1 << 16)
+#define PWUP		(1 << 25)
+
+/* MC13892_REG_CHARGE */
+
+#define VCHRG0		0
+#define VCHRG1		(1 << 1)
+#define VCHRG2		(1 << 2)
+#define ICHRG0		(1 << 3)
+#define ICHRG1		(1 << 4)
+#define ICHRG2		(1 << 5)
+#define ICHRG3		(1 << 6)
+#define ICHRGTR0	(1 << 7)
+#define ICHRGTR1	(1 << 8)
+#define ICHRGTR2	(1 << 9)
+#define FETOVRD		(1 << 10)
+#define FETCTRL		(1 << 11)
+#define RVRSMODE	(1 << 13)
+#define OVCTRL0		(1 << 15)
+#define OVCTRL1		(1 << 16)
+#define UCHEN		(1 << 17)
+#define CHRGLEDEN	(1 << 18)
+#define CHRGRAWPDEN	(1 << 19)
+
+/* MC13892_REG_SETTING_0/1 */
+#define VO_1_20V	0
+#define VO_1_30V	1
+#define VO_1_50V	2
+#define VO_1_80V	3
+#define VO_1_10V	4
+#define VO_2_00V	5
+#define VO_2_77V	6
+#define VO_2_40V	7
+
+#define VIOL		0
+#define VDIG		4
+#define VGEN		6
+
+#define mc13892_reg_write(slave, reg, value) mc13892_reg(slave, reg, value, 1)
+#define mc13892_reg_read(slave, reg)	mc13892_reg(slave, reg, 0, 0)
+
+#define set_mc13892_regulator(slave, reg, field, value) do { \
+	mc13892_reg_write(slave, reg, (value << field)) \
+	} while (0)
+
+struct spi_slave *mc13892_spi_probe(void);
+void mc13892_spi_free(struct spi_slave *slave);
+u32 mc13892_reg(struct spi_slave *slave, u32 reg, u32 val, u32 write);
+void mc13892_show_pmic_info(struct spi_slave *slave);
+
+#endif
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH] Added MC13892VK Power Management driver
  2010-03-16 16:18 [U-Boot] [PATCH] Added MC13892VK Power Management driver Stefano Babic
@ 2010-03-20 23:55 ` Tom
  2010-03-22 10:21   ` Stefano Babic
  2010-04-19  7:56 ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Stefano Babic
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 15+ messages in thread
From: Tom @ 2010-03-20 23:55 UTC (permalink / raw)
  To: u-boot

Stefano Babic wrote:
> Added SPI driver for the Power Management  Controller
> used with i.MX51 Processor.
> 

Errors in
imx31_litekeit
imx31_phycore_eet
imx31_ads
imx31_pdk*
  mxc_spi.c: In function 'spi_cfg':
  mxc_spi.c:158: warning: implicit declaration of function ' mxc_get_clock'
  mxc_spi.c:158: error: ' MXC_CSPI_CLK' undeclared (first use in this function)
  mxc_spi.c:158: error: (Each undeclared identifier is reported only once
  mxc_spi.c:158: error: for each function it appears in.)
  mxc_spi.c:197: warning: implicit declaration of function ' MXC_CSPICTRL_SELCHAN'
  mxc_spi.c:199: warning: implicit declaration of function ' MXC_CSPICTRL_PREDIV'
  mxc_spi.c:201: warning: implicit declaration of function ' MXC_CSPICTRL_POSTDIV'
  mxc_spi.c:219: error: ' MXC_CSPICON' undeclared (first use in this function)
  mxc_spi.c:225: error: ' MXC_CSPICON_SSPOL' undeclared (first use in this function)
  mxc_spi.c:227: error: ' MXC_CSPICON_POL' undeclared (first use in this function)
  mxc_spi.c:229: error: ' MXC_CSPICON_PHA' undeclared (first use in this function)
  mxc_spi.c: In function 'spi_setup_slave':
  mxc_spi.c:460: error: 'ctrl_reg' undeclared (first use in this function)

imx51evk
   mxc_spi.c: In function 'decode_cs':
   mxc_spi.c:400: warning: unused variable 'ret'

These must be fixed

> Signed-off-by: Stefano Babic <sbabic@denx.de>
> ---
>  drivers/misc/Makefile           |    1 +
>  drivers/misc/mc13892_spi_pmic.c |  134 +++++++++++++++++++++++++++++++++++
>  include/mc13892.h               |  149 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 284 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/misc/mc13892_spi_pmic.c
>  create mode 100644 include/mc13892.h
> 
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index f6df60f..5847262 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
>  COBJS-$(CONFIG_NS87308) += ns87308.o
>  COBJS-$(CONFIG_STATUS_LED) += status_led.o
>  COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
> +COBJS-$(CONFIG_MC13892_SPI_PMIC) += mc13892_spi_pmic.o
>  
>  COBJS	:= $(COBJS-y)
>  SRCS	:= $(COBJS:.o=.c)
> diff --git a/drivers/misc/mc13892_spi_pmic.c b/drivers/misc/mc13892_spi_pmic.c
> new file mode 100644
> index 0000000..f095fcc
> --- /dev/null
> +++ b/drivers/misc/mc13892_spi_pmic.c
> @@ -0,0 +1,134 @@
> +/*
> + * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <spi.h>
> +#include <asm/errno.h>
> +#include <linux/types.h>
> +
> +u32 mc13892_reg(struct spi_slave *slave, u32 reg, u32 val, u32 write)
> +{
> +	char tx[4];
> +	char rx[4];
> +	int i;
> +	u32 tmp, pmic_tx, pmic_rx;
> +
> +	if (!slave)
> +		return 0;
> +
> +	if (reg > 63 || write > 1) {
> +		printf("<reg num> = %d is invalid. Should be less then 63\n",
> +			reg);
> +		return 0;
> +	}
> +	pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
> +	debug("reg=0x%x, val=0x%08x\n", reg, pmic_tx);
> +
> +	tmp = pmic_tx;
> +	for (i = 0; i < 4; i++) {
> +		tx[i] = (tmp & 0xFF000000) >> 24;
> +		tmp <<= 8;
> +	}

Looks like you are converting for bigendian to little.
It may be better to use one of the cpu_to_little functions
see linux/byteorder/generic.h

> +
> +	if (spi_xfer(slave, 4 << 3, tx, rx,
> +			SPI_XFER_BEGIN | SPI_XFER_END)) {
> +		return -1;
> +	}
> +
> +	if (write) {
> +		tx[0] &= ~(1 << 31);
> +		if (spi_xfer(slave, 4 << 3, tx, rx,
> +			SPI_XFER_BEGIN | SPI_XFER_END)) {
> +			return -1;
> +		}
> +	}
> +
> +	pmic_rx = (rx[0] << 24) | (rx[1] << 16) | (rx[2] << 8) | rx[3];

A conversion of little to big.
Use existing conversion functions


> +	debug("reg=0x%x, val_read=0x%08x 0x%x 0x%x 0x%x 0x%x\n",
> +		reg, pmic_rx, rx[0], rx[1], rx[2], rx[3]);
> +	return pmic_rx;
> +}
> +
> +void mc13892_show_pmic_info(struct spi_slave *slave)
> +{
> +	volatile u32 rev_id;
> +
> +	if (!slave)
> +		return;
> +
> +	rev_id = mc13892_reg(slave, 7, 0, 0);

Be consistent on use of mc13892_reg.
If you have the read/write wrappers, use them.
 From this conext it is difficult to understand that this is a read.

The return is a u32 value, not a pointer so the modifier 'volatile' is
not needed in the declaration of rev_id

> +	debug("PMIC ID: 0x%08x [Rev: ", rev_id);
> +	switch (rev_id & 0x1F) {
> +	case 0x1:
> +		puts("1.0");
> +		break;
> +	case 0x9:
> +		puts("1.1");
> +		break;
> +	case 0xA:
> +		puts("1.2");
> +		break;
> +	case 0x10:
> +		puts("2.0");
> +		break;
> +	case 0x11:
> +		puts("2.1");
> +		break;
> +	case 0x18:
> +		puts("3.0");
> +		break;
> +	case 0x19:
> +		puts("3.1");
> +		break;
> +	case 0x1A:
> +		puts("3.2");
> +		break;
> +	case 0x2:
> +		puts("3.2A");
> +		break;
> +	case 0x1B:
> +		puts("3.3");
> +		break;
> +	case 0x1D:
> +		puts("3.5");
> +		break;
> +	default:
> +		puts("unknown");
> +		break;
> +	}
> +	puts("]\n");
> +}
> +
> +struct spi_slave *mc13892_spi_probe(void)
> +{
> +	return spi_setup_slave(CONFIG_MC13892_SPI_PMIC_BUS,
> +		CONFIG_MC13892_SPI_PMIC_CS,
> +		CONFIG_MC13892_SPI_PMIC_CLK,
> +		CONFIG_MC13892_SPI_PMIC_MODE);
> +}
> +
> +void mc13892_spi_free(struct spi_slave *slave)
> +{
> +	if (slave)
> +		spi_free_slave(slave);
> +}
> diff --git a/include/mc13892.h b/include/mc13892.h
> new file mode 100644
> index 0000000..b57e07b
> --- /dev/null
> +++ b/include/mc13892.h
> @@ -0,0 +1,149 @@
> +/*
> + * (C) Copyright 2010
> + * Stefano Babic, DENX Software Engineering, sbabic at denx.de.
> + *
> + * (C) Copyright 2009 Freescale Semiconductor, Inc.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __MC13892_H__
> +#define __MC13892_H__
> +
> +enum {
> +	MC13892_REG_INT_STATUS0 = 0,
> +	MC13892_REG_INT_MASK0,
> +	MC13892_REG_INT_SENSE0,
> +	MC13892_REG_INT_STATUS1,
> +	MC13892_REG_INT_MASK1,
> +	MC13892_REG_INT_SENSE1,
> +	MC13892_REG_PU_MODE_S,
> +	MC13892_REG_IDENTIFICATION,
> +	MC13892_REG_UNUSED0,
> +	MC13892_REG_ACC0,
> +	MC13892_REG_ACC1,		/*10 */
> +	MC13892_REG_UNUSED1,
> +	MC13892_REG_UNUSED2,
> +	MC13892_REG_POWER_CTL0,
> +	MC13892_REG_POWER_CTL1,
> +	MC13892_REG_POWER_CTL2,
> +	MC13892_REG_REGEN_ASSIGN,
> +	MC13892_REG_UNUSED3,
> +	MC13892_REG_MEM_A,
> +	MC13892_REG_MEM_B,
> +	MC13892_REG_RTC_TIME,		/*20 */
> +	MC13892_REG_RTC_ALARM,
> +	MC13892_REG_RTC_DAY,
> +	MC13892_REG_RTC_DAY_ALARM,
> +	MC13892_REG_SW_0,
> +	MC13892_REG_SW_1,
> +	MC13892_REG_SW_2,
> +	MC13892_REG_SW_3,
> +	MC13892_REG_SW_4,
> +	MC13892_REG_SW_5,
> +	MC13892_REG_SETTING_0,		/*30 */
> +	MC13892_REG_SETTING_1,
> +	MC13892_REG_MODE_0,
> +	MC13892_REG_MODE_1,
> +	MC13892_REG_POWER_MISC,
> +	MC13892_REG_UNUSED4,
> +	MC13892_REG_UNUSED5,
> +	MC13892_REG_UNUSED6,
> +	MC13892_REG_UNUSED7,
> +	MC13892_REG_UNUSED8,
> +	MC13892_REG_UNUSED9,		/*40 */
> +	MC13892_REG_UNUSED10,
> +	MC13892_REG_UNUSED11,
> +	MC13892_REG_ADC0,
> +	MC13892_REG_ADC1,
> +	MC13892_REG_ADC2,
> +	MC13892_REG_ADC3,
> +	MC13892_REG_ADC4,
> +	MC13892_REG_CHARGE,
> +	MC13892_REG_USB0,
> +	MC13892_REG_USB1,		/*50 */
> +	MC13892_REG_LED_CTL0,
> +	MC13892_REG_LED_CTL1,
> +	MC13892_REG_LED_CTL2,
> +	MC13892_REG_LED_CTL3,
> +	MC13892_REG_UNUSED12,
> +	MC13892_REG_UNUSED13,
> +	MC13892_REG_TRIM0,
> +	MC13892_REG_TRIM1,
> +	MC13892_REG_TEST0,
> +	MC13892_REG_TEST1,		/*60 */
> +	MC13892_REG_TEST2,
> +	MC13892_REG_TEST3,
> +	MC13892_REG_TEST4,

This should be converted to the reg access through struct members.

> +};
> +
> +/* MC13892_REG_POWER_MISC */
> +
> +#define PWGT1SPIEN	(1 << 15)
> +#define PWGT2SPIEN	(1 << 16)
> +#define PWUP		(1 << 25)
> +
> +/* MC13892_REG_CHARGE */
> +
> +#define VCHRG0		0
> +#define VCHRG1		(1 << 1)
> +#define VCHRG2		(1 << 2)
> +#define ICHRG0		(1 << 3)
> +#define ICHRG1		(1 << 4)
> +#define ICHRG2		(1 << 5)
> +#define ICHRG3		(1 << 6)
> +#define ICHRGTR0	(1 << 7)
> +#define ICHRGTR1	(1 << 8)
> +#define ICHRGTR2	(1 << 9)
> +#define FETOVRD		(1 << 10)
> +#define FETCTRL		(1 << 11)
> +#define RVRSMODE	(1 << 13)
> +#define OVCTRL0		(1 << 15)
> +#define OVCTRL1		(1 << 16)
> +#define UCHEN		(1 << 17)
> +#define CHRGLEDEN	(1 << 18)
> +#define CHRGRAWPDEN	(1 << 19)
> +
> +/* MC13892_REG_SETTING_0/1 */
> +#define VO_1_20V	0
> +#define VO_1_30V	1
> +#define VO_1_50V	2
> +#define VO_1_80V	3
> +#define VO_1_10V	4
> +#define VO_2_00V	5
> +#define VO_2_77V	6
> +#define VO_2_40V	7
> +
> +#define VIOL		0
> +#define VDIG		4
> +#define VGEN		6
> +
> +#define mc13892_reg_write(slave, reg, value) mc13892_reg(slave, reg, value, 1)
> +#define mc13892_reg_read(slave, reg)	mc13892_reg(slave, reg, 0, 0)

These wrappers add an unneeded layer of indirection
There should be real read / write funtions

Tom

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH] Added MC13892VK Power Management driver
  2010-03-20 23:55 ` Tom
@ 2010-03-22 10:21   ` Stefano Babic
  0 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2010-03-22 10:21 UTC (permalink / raw)
  To: u-boot

Hi Tom,

Tom wrote:
> Stefano Babic wrote:
>> Added SPI driver for the Power Management  Controller
>> used with i.MX51 Processor.
>>
> 
> Errors in
> imx31_litekeit
> imx31_phycore_eet
> imx31_ads
> These must be fixed

...and I have to test with a MX31, too. I will find a board and test the
changes before sending version 2 of the patch.

>> +
>> +    tmp = pmic_tx;
>> +    for (i = 0; i < 4; i++) {
>> +        tx[i] = (tmp & 0xFF000000) >> 24;
>> +        tmp <<= 8;
>> +    }
> 
> Looks like you are converting for bigendian to little.
> It may be better to use one of the cpu_to_little functions
> see linux/byteorder/generic.h

Thanks, I will check it.

>> +    pmic_rx = (rx[0] << 24) | (rx[1] << 16) | (rx[2] << 8) | rx[3];
> 
> A conversion of little to big.
> Use existing conversion functions

ok, thanks.

>> +    rev_id = mc13892_reg(slave, 7, 0, 0);
> 
> Be consistent on use of mc13892_reg.
> If you have the read/write wrappers, use them.
> From this conext it is difficult to understand that this is a read.

Agree, this is a mistake, I forget to correct it, mc13892_reg() must not
be used outside the driver.

> 
> The return is a u32 value, not a pointer so the modifier 'volatile' is
> not needed in the declaration of rev_id

Ok, got it.


>> +    MC13892_REG_LED_CTL2,
>> +    MC13892_REG_LED_CTL3,
>> +    MC13892_REG_UNUSED12,
>> +    MC13892_REG_UNUSED13,
>> +    MC13892_REG_TRIM0,
>> +    MC13892_REG_TRIM1,
>> +    MC13892_REG_TEST0,
>> +    MC13892_REG_TEST1,        /*60 */
>> +    MC13892_REG_TEST2,
>> +    MC13892_REG_TEST3,
>> +    MC13892_REG_TEST4,
> 
> This should be converted to the reg access through struct members.

I do not know if this helps to make code more readable. We need to send
the address of the internal register via the SPI interface, and these
registers are not mapped into the microprocessor address space.
If I use a structure, I must always convert the address to the register
number before sending via the SPI interface. At the end, I have a
further step that probably makes difficult to understand.

The same approach with register number is actually used for
drivers/rtc/mc13873-rtc.c, whose interface is quite similar as this one,
even if in this case the register number is directly used. I think it is
better to have the same approach for similar chips.

> These wrappers add an unneeded layer of indirection
> There should be real read / write funtions

Agree, I will remove that indirection and avoid to export mc13892_reg.

Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver
  2010-03-16 16:18 [U-Boot] [PATCH] Added MC13892VK Power Management driver Stefano Babic
  2010-03-20 23:55 ` Tom
@ 2010-04-19  7:56 ` Stefano Babic
  2010-04-19  7:56   ` [U-Boot] [PATCH 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
  2010-04-19 18:42   ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Magnus Lilja
  2010-04-19 21:04 ` [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
  2010-04-19 21:06 ` [U-Boot] [PATCH V3 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic
  3 siblings, 2 replies; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:56 UTC (permalink / raw)
  To: u-boot

The patch add supports for the Freescale's Power
Management Controller (known as Atlas) used together with i.MX31/51
processors. It was tested with a MC13783 (MX31) and
MC13892 (MX51).

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

This replaces: Added MC13892VK Power Management driver.
As I saw that the same code could be used for both
Power Management controllers MC13873/MC13892, I changed
the name in a more neutral way, as Freescale already did.

Main changes from the first version:

Comments by Tom Rix:
  - removed unneeded endianess conversions
  - use coherent of accessors function
  - hide slave structure inside the driver
    to avoid the caller mus always check for 
    its status

As reported by Tom, the original patches must be combined into a 
patchset. It was tested on both processors i-MX31 (QONG) and
i.MX51(mx51evk).

 drivers/misc/Makefile   |    1 +
 drivers/misc/fsl_pmic.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++
 include/fsl_pmic.h      |  128 ++++++++++++++++++++++++++++++
 3 files changed, 329 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/fsl_pmic.c
 create mode 100644 include/fsl_pmic.h

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f6df60f..96aa331 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
 COBJS-$(CONFIG_NS87308) += ns87308.o
 COBJS-$(CONFIG_STATUS_LED) += status_led.o
 COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
+COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/misc/fsl_pmic.c b/drivers/misc/fsl_pmic.c
new file mode 100644
index 0000000..87f0aed
--- /dev/null
+++ b/drivers/misc/fsl_pmic.c
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <linux/types.h>
+#include <fsl_pmic.h>
+
+static struct spi_slave *slave;
+
+struct spi_slave *pmic_spi_probe(void)
+{
+	return spi_setup_slave(CONFIG_FSL_PMIC_BUS,
+		CONFIG_FSL_PMIC_CS,
+		CONFIG_FSL_PMIC_CLK,
+		CONFIG_FSL_PMIC_MODE);
+}
+
+void pmic_spi_free(struct spi_slave *slave)
+{
+	if (slave)
+		spi_free_slave(slave);
+}
+
+u32 pmic_reg(u32 reg, u32 val, u32 write)
+{
+	u32 pmic_tx, pmic_rx;
+
+	if (!slave) {
+		slave = pmic_spi_probe();
+
+		if (!slave)
+			return -1;
+	}
+
+	if (reg > 63 || write > 1) {
+		printf("<reg num> = %d is invalid. Should be less then 63\n",
+			reg);
+		return -1;
+	}
+
+	if (spi_claim_bus(slave))
+		return -1;
+
+	pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
+
+	if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
+			SPI_XFER_BEGIN | SPI_XFER_END)) {
+		spi_release_bus(slave);
+		return -1;
+	}
+
+	if (write) {
+		pmic_tx &= ~(1 << 31);
+		if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
+			SPI_XFER_BEGIN | SPI_XFER_END)) {
+			spi_release_bus(slave);
+			return -1;
+		}
+	}
+
+	spi_release_bus(slave);
+	return pmic_rx;
+}
+
+void pmic_reg_write(u32 reg, u32 value)
+{
+	pmic_reg(reg, value, 1);
+}
+
+u32 pmic_reg_read(u32 reg)
+{
+	return pmic_reg(reg, 0, 0);
+}
+
+void pmic_show_pmic_info(void)
+{
+	u32 rev_id;
+
+	rev_id = pmic_reg_read(REG_IDENTIFICATION);
+	printf("PMIC ID: 0x%08x [Rev: ", rev_id);
+	switch (rev_id & 0x1F) {
+	case 0x1:
+		puts("1.0");
+		break;
+	case 0x9:
+		puts("1.1");
+		break;
+	case 0xA:
+		puts("1.2");
+		break;
+	case 0x10:
+		puts("2.0");
+		break;
+	case 0x11:
+		puts("2.1");
+		break;
+	case 0x18:
+		puts("3.0");
+		break;
+	case 0x19:
+		puts("3.1");
+		break;
+	case 0x1A:
+		puts("3.2");
+		break;
+	case 0x2:
+		puts("3.2A");
+		break;
+	case 0x1B:
+		puts("3.3");
+		break;
+	case 0x1D:
+		puts("3.5");
+		break;
+	default:
+		puts("unknown");
+		break;
+	}
+	puts("]\n");
+}
+
+static void pmic_dump(int numregs)
+{
+	u32 val;
+	int i;
+
+	pmic_show_pmic_info();
+	for (i = 0; i < numregs; i++) {
+		val = pmic_reg_read(i);
+		if (!(i % 8))
+			printf ("\n0x%02x: ", i);
+		printf("%08x ", val);
+	}
+	puts("\n");
+}
+
+int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	char *cmd;
+	int nregs;
+	u32 val;
+
+	/*@least two arguments please */
+	if (argc < 2) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	cmd = argv[1];
+	if (strcmp(cmd, "dump") == 0) {
+		if (argc < 3) {
+			cmd_usage(cmdtp);
+			return 1;
+		}
+		nregs = simple_strtoul(argv[2], NULL, 16);
+		pmic_dump(nregs);
+		return 0;
+	}
+	if (strcmp(cmd, "write") == 0) {
+		if (argc < 4) {
+			cmd_usage(cmdtp);
+			return 1;
+		}
+		nregs = simple_strtoul(argv[2], NULL, 16);
+		val = simple_strtoul(argv[3], NULL, 16);
+		pmic_reg_write(nregs, val);
+		return 0;
+	}
+	/* No subcommand found */
+	return 1;
+}
+
+U_BOOT_CMD(
+	pmic,	CONFIG_SYS_MAXARGS, 1, do_pmic,
+	"Freescale PMIC (Atlas)",
+	"dump [numregs] dump registers\n"
+	"pmic write <reg> <value> - write register"
+);
diff --git a/include/fsl_pmic.h b/include/fsl_pmic.h
new file mode 100644
index 0000000..e3abde6
--- /dev/null
+++ b/include/fsl_pmic.h
@@ -0,0 +1,128 @@
+/*
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic at denx.de.
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_PMIC_H__
+#define __FSL_PMIC_H__
+
+/*
+ * The registers of different PMIC has the same meaning
+ * but the bit positions of the fields can differ or
+ * some fields has a meaning only on some devices.
+ * You have to check with the internal SPI bitmap
+ * (see Freescale Documentation) to set the registers
+ * for the device you are using
+ */
+enum {
+	REG_INT_STATUS0 = 0,
+	REG_INT_MASK0,
+	REG_INT_SENSE0,
+	REG_INT_STATUS1,
+	REG_INT_MASK1,
+	REG_INT_SENSE1,
+	REG_PU_MODE_S,
+	REG_IDENTIFICATION,
+	REG_UNUSED0,
+	REG_ACC0,
+	REG_ACC1,		/*10 */
+	REG_UNUSED1,
+	REG_UNUSED2,
+	REG_POWER_CTL0,
+	REG_POWER_CTL1,
+	REG_POWER_CTL2,
+	REG_REGEN_ASSIGN,
+	REG_UNUSED3,
+	REG_MEM_A,
+	REG_MEM_B,
+	REG_RTC_TIME,		/*20 */
+	REG_RTC_ALARM,
+	REG_RTC_DAY,
+	REG_RTC_DAY_ALARM,
+	REG_SW_0,
+	REG_SW_1,
+	REG_SW_2,
+	REG_SW_3,
+	REG_SW_4,
+	REG_SW_5,
+	REG_SETTING_0,		/*30 */
+	REG_SETTING_1,
+	REG_MODE_0,
+	REG_MODE_1,
+	REG_POWER_MISC,
+	REG_UNUSED4,
+	REG_UNUSED5,
+	REG_UNUSED6,
+	REG_UNUSED7,
+	REG_UNUSED8,
+	REG_UNUSED9,		/*40 */
+	REG_UNUSED10,
+	REG_UNUSED11,
+	REG_ADC0,
+	REG_ADC1,
+	REG_ADC2,
+	REG_ADC3,
+	REG_ADC4,
+	REG_CHARGE,
+	REG_USB0,
+	REG_USB1,		/*50 */
+	REG_LED_CTL0,
+	REG_LED_CTL1,
+	REG_LED_CTL2,
+	REG_LED_CTL3,
+	REG_UNUSED12,
+	REG_UNUSED13,
+	REG_TRIM0,
+	REG_TRIM1,
+	REG_TEST0,
+	REG_TEST1,		/*60 */
+	REG_TEST2,
+	REG_TEST3,
+	REG_TEST4,
+};
+
+/* REG_POWER_MISC */
+#define GPO1EN		(1 << 6)
+#define GPO1STBY	(1 << 7)
+#define GPO2EN		(1 << 8)
+#define GPO2STBY	(1 << 9)
+#define GPO3EN		(1 << 10)
+#define GPO3STBY	(1 << 11)
+#define GPO4EN		(1 << 12)
+#define GPO4STBY	(1 << 13)
+#define PWGT1SPIEN	(1 << 15)
+#define PWGT2SPIEN	(1 << 16)
+#define PWUP		(1 << 21)
+
+/* Power Control 0 */
+#define COINCHEN	(1 << 23)
+#define BATTDETEN	(1 << 19)
+
+/* Interrupt status 1 */
+#define RTCRSTI		(1 << 7)
+
+void pmic_show_pmic_info(void);
+void pmic_reg_write(u32 reg, u32 value);
+u32 pmic_reg_read(u32 reg);
+
+#endif
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 2/6] MX: RTC13783 uses general function to access PMIC
  2010-04-19  7:56 ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Stefano Babic
@ 2010-04-19  7:56   ` Stefano Babic
  2010-04-19  7:56     ` [U-Boot] [PATCH 3/6] MX31: Add support for PMIC to the QONG module Stefano Babic
  2010-04-19 18:42   ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Magnus Lilja
  1 sibling, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:56 UTC (permalink / raw)
  To: u-boot

The RTC is part of the Freescale's PMIC controller.
Use general function to access to PMIC internal registers.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 drivers/rtc/mc13783-rtc.c |   72 +++++++++-----------------------------------
 1 files changed, 15 insertions(+), 57 deletions(-)

diff --git a/drivers/rtc/mc13783-rtc.c b/drivers/rtc/mc13783-rtc.c
index 416f50d..4e18f80 100644
--- a/drivers/rtc/mc13783-rtc.c
+++ b/drivers/rtc/mc13783-rtc.c
@@ -23,53 +23,30 @@
 #include <common.h>
 #include <rtc.h>
 #include <spi.h>
-
-static struct spi_slave *slave;
+#include <fsl_pmic.h>
 
 int rtc_get(struct rtc_time *rtc)
 {
 	u32 day1, day2, time;
-	u32 reg;
-	int err, tim, i = 0;
-
-	if (!slave) {
-		/* FIXME: Verify the max SCK rate */
-		slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
-				CONFIG_MC13783_SPI_CS, 1000000,
-				SPI_MODE_2 | SPI_CS_HIGH);
-		if (!slave)
-			return -1;
-	}
-
-	if (spi_claim_bus(slave))
-		return -1;
+	int tim, i = 0;
 
 	do {
-		reg = 0x2c000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
-				SPI_XFER_BEGIN | SPI_XFER_END);
-
-		if (err)
-			return err;
-
-		reg = 0x28000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
-				SPI_XFER_BEGIN | SPI_XFER_END);
+		day1 = pmic_reg_read(REG_RTC_DAY);
+		if (day1 < 0)
+			return -1;
 
-		if (err)
-			return err;
+		time = pmic_reg_read(REG_RTC_TIME);
+		if (time < 0)
+			return -1;
 
-		reg = 0x2c000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
-				SPI_XFER_BEGIN | SPI_XFER_END);
+		day2 = pmic_reg_read(REG_RTC_DAY);
+		if (day2 < 0)
+			return -1;
 
-		if (err)
-			return err;
 	} while (day1 != day2 && i++ < 3);
 
-	spi_release_bus(slave);
-
 	tim = day1 * 86400 + time;
+
 	to_tm(tim, rtc);
 
 	rtc->tm_yday = 0;
@@ -80,34 +57,15 @@ int rtc_get(struct rtc_time *rtc)
 
 int rtc_set(struct rtc_time *rtc)
 {
-	u32 time, day, reg;
-
-	if (!slave) {
-		/* FIXME: Verify the max SCK rate */
-		slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
-				CONFIG_MC13783_SPI_CS, 1000000,
-				SPI_MODE_2 | SPI_CS_HIGH);
-		if (!slave)
-			return -1;
-	}
+	u32 time, day;
 
 	time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
 		      rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
 	day = time / 86400;
 	time %= 86400;
 
-	if (spi_claim_bus(slave))
-		return -1;
-
-	reg = 0x2c000000 | day | 0x80000000;
-	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day,
-			SPI_XFER_BEGIN | SPI_XFER_END);
-
-	reg = 0x28000000 | time | 0x80000000;
-	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
-			SPI_XFER_BEGIN | SPI_XFER_END);
-
-	spi_release_bus(slave);
+	pmic_reg_write(REG_RTC_DAY, day);
+	pmic_reg_write(REG_RTC_TIME, time);
 
 	return 0;
 }
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 3/6] MX31: Add support for PMIC to the QONG module
  2010-04-19  7:56   ` [U-Boot] [PATCH 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
@ 2010-04-19  7:56     ` Stefano Babic
  2010-04-19  7:56       ` [U-Boot] [PATCH V2 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic
  0 siblings, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:56 UTC (permalink / raw)
  To: u-boot

Add support for the PMIC (MC13783) controller
and enables charging of the RTC battery.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 board/davedenx/qong/qong.c |   20 ++++++++++++++++++++
 include/configs/qong.h     |   14 ++++++++++++++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/board/davedenx/qong/qong.c b/board/davedenx/qong/qong.c
index eb9218e..781333b 100644
--- a/board/davedenx/qong/qong.c
+++ b/board/davedenx/qong/qong.c
@@ -26,6 +26,7 @@
 #include <asm/arch/mx31.h>
 #include <asm/arch/mx31-regs.h>
 #include <nand.h>
+#include <fsl_pmic.h>
 #include "qong_fpga.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -128,6 +129,13 @@ int board_init (void)
 	mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
 	mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
 
+	/* setup pins for SPI (pmic) */
+	mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
+	mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
+	mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
+	mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
+	mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
+
 	/* board id for linux */
 	gd->bd->bi_arch_number = MACH_TYPE_QONG;
 	gd->bd->bi_boot_params = (0x80000100);	/* adress of boot parameters */
@@ -135,6 +143,18 @@ int board_init (void)
 	return 0;
 }
 
+int board_late_init(void)
+{
+	u32 val;
+
+	/* Enable RTC battery */
+	val = pmic_reg_read(REG_POWER_CTL0);
+	pmic_reg_write(REG_POWER_CTL0, val | COINCHEN);
+	pmic_reg_write(REG_INT_STATUS1, RTCRSTI);
+
+	return 0;
+}
+
 int checkboard (void)
 {
 	printf("Board: DAVE/DENX Qong\n");
diff --git a/include/configs/qong.h b/include/configs/qong.h
index 178c8e7..1d187d0 100644
--- a/include/configs/qong.h
+++ b/include/configs/qong.h
@@ -54,6 +54,17 @@
 
 #define CONFIG_MX31_GPIO
 
+#define CONFIG_MXC_SPI
+#define CONFIG_DEFAULT_SPI_BUS	1
+#define CONFIG_DEFAULT_SPI_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
+#define CONFIG_RTC_MC13783
+
+#define CONFIG_FSL_PMIC
+#define CONFIG_FSL_PMIC_BUS	1
+#define CONFIG_FSL_PMIC_CS	0
+#define CONFIG_FSL_PMIC_CLK	100000
+#define CONFIG_FSL_PMIC_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
+
 /* FPGA */
 #define CONFIG_QONG_FPGA	1
 #define CONFIG_FPGA_BASE	(CS1_BASE)
@@ -87,6 +98,9 @@
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_DATE
+#define BOARD_LATE_INIT
 
 /*
  * You can compile in a MAC address and your custom net settings by using
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V2 4/6] SPI: added support for MX51 to mxc_spi
  2010-04-19  7:56     ` [U-Boot] [PATCH 3/6] MX31: Add support for PMIC to the QONG module Stefano Babic
@ 2010-04-19  7:56       ` Stefano Babic
  2010-04-19  7:56         ` [U-Boot] [PATCH 5/6] MX: Added definition file for MC13892 Stefano Babic
  0 siblings, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:56 UTC (permalink / raw)
  To: u-boot

This patch add SPI support for the MX51 processor.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

This is the second version to get support for MX51 in the driver.
As reported by Tom Rix, the previous patch broke several MX31 boards
and mixed supporting the MX51 processor with fixing some issues.
This patch adds only support for the MX51 processor and postpone
(if required) supporting not-word aligned buffers to a later patch.

Other changes I can summarize:

Comments from Tom Rix:
	- do no make common definition of certain registers
	- consistency inside code

Comments from Liu Hui:
	- most comments drop out because are related to fix
	not word aligned buffers.
	- added CONFIG_MX51 to protect only MX51 related code

 drivers/spi/mxc_spi.c |  231 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 210 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 3a45200..65f43ad 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -31,7 +31,7 @@
 #error "i.MX27 CSPI not supported due to drastic differences in register definisions" \
 "See linux mxc_spi driver from Freescale for details."
 
-#else
+#elif defined(CONFIG_MX31)
 
 #include <asm/arch/mx31.h>
 
@@ -56,6 +56,9 @@
 #define MXC_CSPICTRL_CHIPSELECT(x)	(((x) & 0x3) << 24)
 #define MXC_CSPICTRL_BITCOUNT(x)	(((x) & 0x1f) << 8)
 #define MXC_CSPICTRL_DATARATE(x)	(((x) & 0x7) << 16)
+#define MXC_CSPICTRL_TC		(1 << 8)
+#define MXC_CSPICTRL_RXOVF	(1 << 6)
+#define MXC_CSPICTRL_MAXBITS	0x1f
 
 #define MXC_CSPIPERIOD_32KHZ	(1 << 15)
 
@@ -65,12 +68,63 @@ static unsigned long spi_bases[] = {
 	0x53f84000,
 };
 
+#define OUT	MX31_GPIO_DIRECTION_OUT
+#define mxc_gpio_direction	mx31_gpio_direction
+#define mxc_gpio_set		mx31_gpio_set
+#elif defined(CONFIG_MX51)
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#define MXC_CSPIRXDATA		0x00
+#define MXC_CSPITXDATA		0x04
+#define MXC_CSPICTRL		0x08
+#define MXC_CSPICON		0x0C
+#define MXC_CSPIINT		0x10
+#define MXC_CSPIDMA		0x14
+#define MXC_CSPISTAT		0x18
+#define MXC_CSPIPERIOD		0x1C
+#define MXC_CSPIRESET		0x00
+#define MXC_CSPICTRL_EN		(1 << 0)
+#define MXC_CSPICTRL_MODE	(1 << 1)
+#define MXC_CSPICTRL_XCH	(1 << 2)
+#define MXC_CSPICTRL_CHIPSELECT(x)	(((x) & 0x3) << 12)
+#define MXC_CSPICTRL_BITCOUNT(x)	(((x) & 0xfff) << 20)
+#define MXC_CSPICTRL_PREDIV(x)	(((x) & 0xF) << 12)
+#define MXC_CSPICTRL_POSTDIV(x)	(((x) & 0xF) << 8)
+#define MXC_CSPICTRL_SELCHAN(x)	(((x) & 0x3) << 18)
+#define MXC_CSPICTRL_MAXBITS	0xfff
+#define MXC_CSPICTRL_TC		(1 << 7)
+#define MXC_CSPICTRL_RXOVF	(1 << 6)
+
+#define MXC_CSPIPERIOD_32KHZ	(1 << 15)
+
+/* Bit position inside CTRL register to be associated with SS */
+#define MXC_CSPICTRL_CHAN	18
+
+/* Bit position inside CON register to be associated with SS */
+#define MXC_CSPICON_POL		4
+#define MXC_CSPICON_PHA		0
+#define MXC_CSPICON_SSPOL	12
+
+static unsigned long spi_bases[] = {
+	CSPI1_BASE_ADDR,
+	CSPI2_BASE_ADDR,
+	CSPI3_BASE_ADDR,
+};
+#define mxc_gpio_direction(gpio, dir)	(0)
+#define mxc_gpio_set(gpio, value)	{}
+#define OUT	1
+#else
+#error "Unsupported architecture"
 #endif
 
 struct mxc_spi_slave {
 	struct spi_slave slave;
 	unsigned long	base;
 	u32		ctrl_reg;
+#if defined(CONFIG_MX51)
+	u32		cfg_reg;
+#endif
 	int		gpio;
 };
 
@@ -89,34 +143,161 @@ static inline void reg_write(unsigned long addr, u32 val)
 	*(volatile unsigned long*)addr = val;
 }
 
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+	if (mxcs->gpio > 0)
+		mxc_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+	if (mxcs->gpio > 0)
+		mxc_gpio_set(mxcs->gpio,
+			      !(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
+}
+
+#ifdef CONFIG_MX51
+static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
+	s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
+	u32 ss_pol = 0, sclkpol = 0, sclkpha = 0;
+
+	if (max_hz == 0) {
+		printf("Error: desired clock is 0\n");
+		return -1;
+	}
+
+	reg_ctrl = reg_read(mxcs->base + MXC_CSPICTRL);
+
+	/* Reset spi */
+	reg_write(mxcs->base + MXC_CSPICTRL, 0);
+	reg_write(mxcs->base + MXC_CSPICTRL, (reg_ctrl | 0x1));
+
+	/*
+	 * The following computation is taken directly from Freescale's code.
+	 */
+	if (clk_src > max_hz) {
+		pre_div = clk_src / max_hz;
+		if (pre_div > 16) {
+			post_div = pre_div / 16;
+			pre_div = 15;
+		}
+		if (post_div != 0) {
+			for (i = 0; i < 16; i++) {
+				if ((1 << i) >= post_div)
+					break;
+			}
+			if (i == 16) {
+				printf("Error: no divider for the freq: %d\n",
+					max_hz);
+				return -1;
+			}
+			post_div = i;
+		}
+	}
+
+	debug("pre_div = %d, post_div=%d\n", pre_div, post_div);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_SELCHAN(3)) |
+		MXC_CSPICTRL_SELCHAN(cs);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_PREDIV(0x0F)) |
+		MXC_CSPICTRL_PREDIV(pre_div);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
+		MXC_CSPICTRL_POSTDIV(post_div);
+
+	/* always set to master mode */
+	reg_ctrl |= 1 << (cs + 4);
+
+	/* We need to disable SPI before changing registers */
+	reg_ctrl &= ~MXC_CSPICTRL_EN;
+
+	if (mode & SPI_CS_HIGH)
+		ss_pol = 1;
+
+	if (!(mode & SPI_CPOL))
+		sclkpol = 1;
+
+	if (mode & SPI_CPHA)
+		sclkpha = 1;
+
+	reg_config = reg_read(mxcs->base + MXC_CSPICON);
+
+	/*
+	 * Configuration register setup
+	 * The MX51 has support different setup for each SS
+	 */
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
+		(ss_pol << (cs + MXC_CSPICON_SSPOL));
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_POL))) |
+		(sclkpol << (cs + MXC_CSPICON_POL));
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_PHA))) |
+		(sclkpha << (cs + MXC_CSPICON_PHA));
+
+	debug("reg_ctrl = 0x%x\n", reg_ctrl);
+	reg_write(mxcs->base + MXC_CSPICTRL, reg_ctrl);
+	debug("reg_config = 0x%x\n", reg_config);
+	reg_write(mxcs->base + MXC_CSPICON, reg_config);
+
+	/* save config register and control register */
+	mxcs->ctrl_reg = reg_ctrl;
+	mxcs->cfg_reg = reg_config;
+
+	/* clear interrupt reg */
+	reg_write(mxcs->base + MXC_CSPIINT, 0);
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+	return 0;
+}
+#endif
+
 static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
 			   unsigned long flags)
 {
 	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL);
 
-	mxcs->ctrl_reg = (mxcs->ctrl_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
+	if (flags & SPI_XFER_BEGIN)
+		spi_cs_activate(slave);
+
+	mxcs->ctrl_reg = (mxcs->ctrl_reg &
+		~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
 		MXC_CSPICTRL_BITCOUNT(bitlen - 1);
 
-	if (cfg_reg != mxcs->ctrl_reg)
-		reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
+	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
+#ifdef CONFIG_MX51
+	reg_write(mxcs->base + MXC_CSPICON, mxcs->cfg_reg);
+#endif
 
-	if (mxcs->gpio > 0 && (flags & SPI_XFER_BEGIN))
-		mx31_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
+	/* Clear interrupt register */
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 
+	debug("Sending SPI 0x%x\n", data);
 	reg_write(mxcs->base + MXC_CSPITXDATA, data);
 
-	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_XCH);
+	/* FIFO is written, now starts the transfer setting the XCH bit */
+	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg |
+		MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
 
-	while (reg_read(mxcs->base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH)
+	/* Wait until the TC (Transfer completed) bit is set */
+	while ((reg_read(mxcs->base + MXC_CSPISTAT) & MXC_CSPICTRL_TC) == 0)
 		;
 
-	if (mxcs->gpio > 0 && (flags & SPI_XFER_END)) {
-		mx31_gpio_set(mxcs->gpio,
-			      !(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
-	}
+	/* Transfer completed, clear any pending request */
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+	data = reg_read(mxcs->base + MXC_CSPIRXDATA);
+	debug("SPI Rx: 0x%x\n", data);
+
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	return data;
 
-	return reg_read(mxcs->base + MXC_CSPIRXDATA);
 }
 
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
@@ -176,7 +357,7 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
 	if (cs > 3) {
 		mxcs->gpio = cs >> 8;
 		cs &= 3;
-		ret = mx31_gpio_direction(mxcs->gpio, MX31_GPIO_DIRECTION_OUT);
+		ret = mxc_gpio_direction(mxcs->gpio, OUT);
 		if (ret) {
 			printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
 			return -EINVAL;
@@ -191,7 +372,6 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 			unsigned int max_hz, unsigned int mode)
 {
-	unsigned int ctrl_reg;
 	struct mxc_spi_slave *mxcs;
 	int ret;
 
@@ -210,6 +390,19 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
 	cs = ret;
 
+	mxcs->slave.bus = bus;
+	mxcs->slave.cs = cs;
+	mxcs->base = spi_bases[bus];
+
+#ifdef CONFIG_MX51
+	/* Can be used for i.MX31 too ? */
+	ret = spi_cfg(mxcs, cs, max_hz, mode);
+	if (ret) {
+		printf("mxc_spi: cannot setup SPI controller\n");
+		free(mxcs);
+		return NULL;
+	}
+#else
 	ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
 		MXC_CSPICTRL_BITCOUNT(31) |
 		MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */
@@ -222,12 +415,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		ctrl_reg |= MXC_CSPICTRL_POL;
 	if (mode & SPI_CS_HIGH)
 		ctrl_reg |= MXC_CSPICTRL_SSPOL;
-
-	mxcs->slave.bus = bus;
-	mxcs->slave.cs = cs;
-	mxcs->base = spi_bases[bus];
 	mxcs->ctrl_reg = ctrl_reg;
-
+#endif
 	return &mxcs->slave;
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 5/6] MX: Added definition file for MC13892
  2010-04-19  7:56       ` [U-Boot] [PATCH V2 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic
@ 2010-04-19  7:56         ` Stefano Babic
  2010-04-19  7:57           ` [U-Boot] [PATCH V2 6/6] Add SPI support to mx51evk board Stefano Babic
  0 siblings, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:56 UTC (permalink / raw)
  To: u-boot

The MC13892 is a Power Controller used with processors
of the family MX.51. The file adds definitions to be used to setup
the internal registers via SPI.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 include/mc13892.h |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100644 include/mc13892.h

diff --git a/include/mc13892.h b/include/mc13892.h
new file mode 100644
index 0000000..b291757
--- /dev/null
+++ b/include/mc13892.h
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic at denx.de.
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#ifndef __MC13892_H__
+#define __MC13892_H__
+
+/* REG_CHARGE */
+
+#define VCHRG0		0
+#define VCHRG1		(1 << 1)
+#define VCHRG2		(1 << 2)
+#define ICHRG0		(1 << 3)
+#define ICHRG1		(1 << 4)
+#define ICHRG2		(1 << 5)
+#define ICHRG3		(1 << 6)
+#define ICHRGTR0	(1 << 7)
+#define ICHRGTR1	(1 << 8)
+#define ICHRGTR2	(1 << 9)
+#define FETOVRD		(1 << 10)
+#define FETCTRL		(1 << 11)
+#define RVRSMODE	(1 << 13)
+#define OVCTRL0		(1 << 15)
+#define OVCTRL1		(1 << 16)
+#define UCHEN		(1 << 17)
+#define CHRGLEDEN	(1 << 18)
+#define CHRGRAWPDEN	(1 << 19)
+#define CHGRESTART	(1 << 20)
+#define CHGAUTOB	(1 << 21)
+#define CYCLB		(1 << 22)
+#define CHGAUTOVIB	(1 << 23)
+
+/* REG_SETTING_0/1 */
+#define VO_1_20V	0
+#define VO_1_30V	1
+#define VO_1_50V	2
+#define VO_1_80V	3
+#define VO_1_10V	4
+#define VO_2_00V	5
+#define VO_2_77V	6
+#define VO_2_40V	7
+
+#define VIOL		2
+#define VDIG		4
+#define VGEN		6
+
+/* SWxMode for Normal/Standby Mode */
+#define SWMODE_OFF_OFF		0
+#define SWMODE_PWM_OFF		1
+#define SWMODE_PWMPS_OFF	2
+#define SWMODE_PFM_OFF		3
+#define SWMODE_AUTO_OFF		4
+#define SWMODE_PWM_PWM		5
+#define SWMODE_PWM_AUTO		6
+#define SWMODE_AUTO_AUTO	8
+#define SWMODE_PWM_PWMPS	9
+#define SWMODE_PWMS_PWMPS	10
+#define SWMODE_PWMS_AUTO	11
+#define SWMODE_AUTO_PFM		12
+#define SWMODE_PWM_PFM		13
+#define SWMODE_PWMS_PFM		14
+#define SWMODE_PFM_PFM		15
+#define SWMODE_MASK		0x0F
+
+#define SWMODE1_SHIFT		0
+#define SWMODE2_SHIFT		10
+#define SWMODE3_SHIFT		0
+#define SWMODE4_SHIFT		8
+
+/* Fields in REG_SETTING_1 */
+#define VVIDEO_2_7	(0 << 2)
+#define VVIDEO_2_775	(1 << 2)
+#define VVIDEO_2_5	(2 << 2)
+#define VVIDEO_2_6	(3 << 2)
+#define VVIDEO_MASK	(3 << 2)
+#define VAUDIO_2_3	(0 << 4)
+#define VAUDIO_2_5	(1 << 4)
+#define VAUDIO_2_775	(2 << 4)
+#define VAUDIO_3_0	(3 << 4)
+#define VAUDIO_MASK	(3 << 4)
+#define VSD_1_8		(0 << 6)
+#define VSD_2_0		(1 << 6)
+#define VSD_2_6		(2 << 6)
+#define VSD_2_7		(3 << 6)
+#define VSD_2_8		(4 << 6)
+#define VSD_2_9		(5 << 6)
+#define VSD_3_0		(6 << 6)
+#define VSD_3_15	(7 << 6)
+#define VSD_MASK	(7 << 6)
+#define VGEN1_1_2	0
+#define VGEN1_1_5	1
+#define VGEN1_2_775	2
+#define VGEN1_3_15	3
+#define VGEN1_MASK	3
+#define VGEN2_1_2	(0 << 6)
+#define VGEN2_1_5	(1 << 6)
+#define VGEN2_1_6	(2 << 6)
+#define VGEN2_1_8	(3 << 6)
+#define VGEN2_2_7	(4 << 6)
+#define VGEN2_2_8	(5 << 6)
+#define VGEN2_3_0	(6 << 6)
+#define VGEN2_3_15	(7 << 6)
+#define VGEN2_MASK	(7 << 6)
+
+/* Fields in REG_SETTING_1 */
+#define VGEN3_1_8	(0 << 14)
+#define VGEN3_2_9	(1 << 14)
+#define VGEN3_MASK	(1 << 14)
+#define VDIG_1_05	(0 << 4)
+#define VDIG_1_25	(1 << 4)
+#define VDIG_1_65	(2 << 4)
+#define VDIG_1_8	(3 << 4)
+#define VDIG_MASK	(3 << 4)
+#define VCAM_2_5	(0 << 16)
+#define VCAM_2_6	(1 << 16)
+#define VCAM_2_75	(2 << 16)
+#define VCAM_3_0	(3 << 16)
+#define VCAM_MASK	(3 << 16)
+
+/* Reg Mode 1 */
+#define VGEN3EN		(1 << 0)
+#define VGEN3STBY	(1 << 1)
+#define VGEN3MODE	(1 << 2)
+#define VGEN3CONFIG	(1 << 3)
+#define VCAMEN		(1 << 6)
+#define VCAMSTBY	(1 << 7)
+#define VCAMMODE	(1 << 8)
+#define VCAMCONFIG	(1 << 9)
+#define VVIDEOEN	(1 << 12)
+#define VIDEOSTBY	(1 << 13)
+#define VVIDEOMODE	(1 << 14)
+#define VAUDIOEN	(1 << 15)
+#define VAUDIOSTBY	(1 << 16)
+#define VSDEN		(1 << 18)
+#define VSDSTBY		(1 << 19)
+#define VSDMODE		(1 << 20)
+
+#endif
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V2 6/6] Add SPI support to mx51evk board
  2010-04-19  7:56         ` [U-Boot] [PATCH 5/6] MX: Added definition file for MC13892 Stefano Babic
@ 2010-04-19  7:57           ` Stefano Babic
  0 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2010-04-19  7:57 UTC (permalink / raw)
  To: u-boot

The patch adds SPI devices to the mx51evk board.
The MC13892 chip (PMIC) is supported.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

Version 2 of the patch is rearranged due to changes in the
mxc_spi driver. Other changes:

Comments by Tom Rix:
	- Atmel SPI flash is not supported - removed
	- Removed unneded define inside C file
	- Replaced all hard-coded values with an or-ing
	of bit

 board/freescale/mx51evk/mx51evk.c |  139 +++++++++++++++++++++++++++++++++++++
 include/configs/mx51evk.h         |   15 ++++
 2 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/board/freescale/mx51evk/mx51evk.c b/board/freescale/mx51evk/mx51evk.c
index f0b7abc..e9f01f6 100644
--- a/board/freescale/mx51evk/mx51evk.c
+++ b/board/freescale/mx51evk/mx51evk.c
@@ -27,9 +27,12 @@
 #include <asm/arch/iomux.h>
 #include <asm/errno.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/crm_regs.h>
 #include <i2c.h>
 #include <mmc.h>
 #include <fsl_esdhc.h>
+#include <fsl_pmic.h>
+#include <mc13892.h>
 #include "mx51evk.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -147,6 +150,130 @@ static void setup_iomux_fec(void)
 	mxc_iomux_set_pad(MX51_PIN_NANDF_D11, 0x2180);
 }
 
+#ifdef CONFIG_MXC_SPI
+static void setup_iomux_spi(void)
+{
+	/* 000: Select mux mode: ALT0 mux port: MOSI of instance: ecspi1 */
+	mxc_request_iomux(MX51_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT0);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_MOSI, 0x105);
+
+	/* 000: Select mux mode: ALT0 mux port: MISO of instance: ecspi1. */
+	mxc_request_iomux(MX51_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT0);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_MISO, 0x105);
+
+	/* de-select SS1 of instance: ecspi1. */
+	mxc_request_iomux(MX51_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT3);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_SS1, 0x85);
+
+	/* 000: Select mux mode: ALT0 mux port: SS0 ecspi1 */
+	mxc_request_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT0);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0, 0x185);
+
+	/* 000: Select mux mode: ALT0 mux port: RDY of instance: ecspi1. */
+	mxc_request_iomux(MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT0);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_RDY, 0x180);
+
+	/* 000: Select mux mode: ALT0 mux port: SCLK of instance: ecspi1. */
+	mxc_request_iomux(MX51_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT0);
+	mxc_iomux_set_pad(MX51_PIN_CSPI1_SCLK, 0x105);
+}
+#endif
+
+static void power_init(void)
+{
+	unsigned int val;
+	unsigned int reg;
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
+
+	/* Write needed to Power Gate 2 register */
+	val = pmic_reg_read(REG_POWER_MISC);
+	val &= ~PWGT2SPIEN;
+	pmic_reg_write(REG_POWER_MISC, val);
+
+	/* Write needed to update Charger 0 */
+	pmic_reg_write(REG_CHARGE, VCHRG0 | VCHRG1 | VCHRG2 |
+		ICHRG0 | ICHRG1 | ICHRG2 | ICHRG3 | ICHRGTR0 |
+		OVCTRL1 | UCHEN | CHRGLEDEN | CYCLB);
+
+	/* power up the system first */
+	pmic_reg_write(REG_POWER_MISC, PWUP);
+
+	/* Set core voltage to 1.1V */
+	val = pmic_reg_read(REG_SW_0);
+	val = (val & (~0x1F)) | 0x14;
+	pmic_reg_write(REG_SW_0, val);
+
+	/* Setup VCC (SW2) to 1.25 */
+	val = pmic_reg_read(REG_SW_1);
+	val = (val & (~0x1F)) | 0x1A;
+	pmic_reg_write(REG_SW_1, val);
+
+	/* Setup 1V2_DIG1 (SW3) to 1.25 */
+	val = pmic_reg_read(REG_SW_2);
+	val = (val & (~0x1F)) | 0x1A;
+	pmic_reg_write(REG_SW_2, val);
+	udelay(50);
+
+	/* Raise the core frequency to 800MHz */
+	writel(0x0, &mxc_ccm->cacrr);
+
+	/* Set switchers in Auto in NORMAL mode & STANDBY mode */
+	/* Setup the switcher mode for SW1 & SW2*/
+	val = pmic_reg_read(REG_SW_4);
+	val = (val & ~((SWMODE_MASK << SWMODE1_SHIFT) |
+		(SWMODE_MASK << SWMODE2_SHIFT)));
+	val |= (SWMODE_AUTO_AUTO << SWMODE1_SHIFT) |
+		(SWMODE_AUTO_AUTO << SWMODE2_SHIFT);
+	pmic_reg_write(REG_SW_4, val);
+
+	/* Setup the switcher mode for SW3 & SW4 */
+	val = pmic_reg_read(REG_SW_5);
+	val = (val & ~((SWMODE_MASK << SWMODE3_SHIFT) |
+		(SWMODE_MASK << SWMODE4_SHIFT)));
+	val |= (SWMODE_AUTO_AUTO << SWMODE3_SHIFT) |
+		(SWMODE_AUTO_AUTO << SWMODE4_SHIFT);
+	pmic_reg_write(REG_SW_5, val);
+
+	/* Set VDIG to 1.65V, VGEN3 to 1.8V, VCAM to 2.6V */
+	val = pmic_reg_read(REG_SETTING_0);
+	val &= ~(VCAM_MASK | VGEN3_MASK | VDIG_MASK);
+	val |= VDIG_1_65 | VGEN3_1_8 | VCAM_2_6;
+	pmic_reg_write(REG_SETTING_0, val);
+
+	/* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
+	val = pmic_reg_read(REG_SETTING_1);
+	val &= ~(VVIDEO_MASK | VSD_MASK | VAUDIO_MASK);
+	val |= VSD_3_15 | VAUDIO_3_0 | VVIDEO_2_775;
+	pmic_reg_write(REG_SETTING_1, val);
+
+	/* Configure VGEN3 and VCAM regulators to use external PNP */
+	val = VGEN3CONFIG | VCAMCONFIG;
+	pmic_reg_write(REG_MODE_1, val);
+	udelay(200);
+
+	reg = readl(GPIO2_BASE_ADDR + 0x0);
+	reg &= ~0x4000;  /* Lower reset line */
+	writel(reg, GPIO2_BASE_ADDR + 0x0);
+
+	reg = readl(GPIO2_BASE_ADDR + 0x4);
+	reg |= 0x4000;	/* configure GPIO lines as output */
+	writel(reg, GPIO2_BASE_ADDR + 0x4);
+
+	/* Reset the ethernet controller over GPIO */
+	writel(0x1, IOMUXC_BASE_ADDR + 0x0AC);
+
+	/* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
+	val = VGEN3EN | VGEN3CONFIG | VCAMEN | VCAMCONFIG |
+		VVIDEOEN | VAUDIOEN  | VSDEN;
+	pmic_reg_write(REG_MODE_1, val);
+
+	udelay(500);
+
+	reg = readl(GPIO2_BASE_ADDR + 0x0);
+	reg |= 0x4000;
+	writel(reg, GPIO2_BASE_ADDR + 0x0);
+}
+
 #ifdef CONFIG_FSL_ESDHC
 int board_mmc_getcd(u8 *cd, struct mmc *mmc)
 {
@@ -284,9 +411,21 @@ int board_init(void)
 
 	setup_iomux_uart();
 	setup_iomux_fec();
+
 	return 0;
 }
 
+#ifdef BOARD_LATE_INIT
+int board_late_init(void)
+{
+#ifdef CONFIG_MXC_SPI
+	setup_iomux_spi();
+	power_init();
+#endif
+	return 0;
+}
+#endif
+
 int checkboard(void)
 {
 	puts("Board: MX51EVK ");
diff --git a/include/configs/mx51evk.h b/include/configs/mx51evk.h
index 3626df7..86a4731 100644
--- a/include/configs/mx51evk.h
+++ b/include/configs/mx51evk.h
@@ -54,6 +54,8 @@
 /* size in bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_SIZE	128
 
+#define BOARD_LATE_INIT
+
 /*
  * Hardware drivers
  */
@@ -61,6 +63,19 @@
 #define CONFIG_SYS_MX51_UART1
 
 /*
+ * SPI Configs
+ * */
+#define CONFIG_CMD_SPI
+
+#define CONFIG_MXC_SPI
+
+#define CONFIG_FSL_PMIC
+#define CONFIG_FSL_PMIC_BUS	0
+#define CONFIG_FSL_PMIC_CS	0
+#define CONFIG_FSL_PMIC_CLK	2500000
+#define CONFIG_FSL_PMIC_MODE	(SPI_CPOL | SPI_CS_HIGH)
+
+/*
  * MMC Configs
  * */
 #define CONFIG_FSL_ESDHC
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver
  2010-04-19  7:56 ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Stefano Babic
  2010-04-19  7:56   ` [U-Boot] [PATCH 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
@ 2010-04-19 18:42   ` Magnus Lilja
  2010-04-19 20:10     ` Stefano Babic
  1 sibling, 1 reply; 15+ messages in thread
From: Magnus Lilja @ 2010-04-19 18:42 UTC (permalink / raw)
  To: u-boot

Hi

On 04/19/2010 09:56 AM, Stefano Babic wrote:
> The patch add supports for the Freescale's Power
> Management Controller (known as Atlas) used together with i.MX31/51
> processors. It was tested with a MC13783 (MX31) and
> MC13892 (MX51).

You should try and compile all i.MX31 boards with your patches. I tried i.MX31 Litekit and it failed:
mxc_spi.c: In function 'spi_setup_slave':
mxc_spi.c:406: error: 'ctrl_reg' undeclared (first use in this function)
mxc_spi.c:406: error: (Each undeclared identifier is reported only once
mxc_spi.c:406: error: for each function it appears in.)

I applied your patches on top of the u-boot-imx-tree.

Regards, Magnus Lilja

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver
  2010-04-19 18:42   ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Magnus Lilja
@ 2010-04-19 20:10     ` Stefano Babic
  0 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2010-04-19 20:10 UTC (permalink / raw)
  To: u-boot

Magnus Lilja wrote:
> Hi
> 

Hi Magnus,

> On 04/19/2010 09:56 AM, Stefano Babic wrote:
>> The patch add supports for the Freescale's Power
>> Management Controller (known as Atlas) used together with i.MX31/51
>> processors. It was tested with a MC13783 (MX31) and
>> MC13892 (MX51).
> 
> You should try and compile all i.MX31 boards with your patches. I tried i.MX31 Litekit and it failed:
> mxc_spi.c: In function 'spi_setup_slave':
> mxc_spi.c:406: error: 'ctrl_reg' undeclared (first use in this function)
> mxc_spi.c:406: error: (Each undeclared identifier is reported only once
> mxc_spi.c:406: error: for each function it appears in.)
> 
> I applied your patches on top of the u-boot-imx-tree.

Thanks for testing, I see. I will check with all MX.31 boards and I will
resubmit an updated version of the patches soon.

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC
  2010-03-16 16:18 [U-Boot] [PATCH] Added MC13892VK Power Management driver Stefano Babic
  2010-03-20 23:55 ` Tom
  2010-04-19  7:56 ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Stefano Babic
@ 2010-04-19 21:04 ` Stefano Babic
  2010-04-22 20:06   ` Magnus Lilja
  2010-04-19 21:06 ` [U-Boot] [PATCH V3 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic
  3 siblings, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2010-04-19 21:04 UTC (permalink / raw)
  To: u-boot

The RTC is part of the Freescale's PMIC controller.
Use general function to access to PMIC internal registers.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

Changes since last version: configuration of the RTC must be
updated for the boards that are using it.

 drivers/rtc/mc13783-rtc.c       |   72 ++++++++------------------------------
 include/configs/imx31_litekit.h |    9 +++--
 include/configs/mx31ads.h       |    8 +++--
 include/configs/mx31pdk.h       |    9 +++--
 4 files changed, 31 insertions(+), 67 deletions(-)

diff --git a/drivers/rtc/mc13783-rtc.c b/drivers/rtc/mc13783-rtc.c
index 416f50d..4e18f80 100644
--- a/drivers/rtc/mc13783-rtc.c
+++ b/drivers/rtc/mc13783-rtc.c
@@ -23,53 +23,30 @@
 #include <common.h>
 #include <rtc.h>
 #include <spi.h>
-
-static struct spi_slave *slave;
+#include <fsl_pmic.h>
 
 int rtc_get(struct rtc_time *rtc)
 {
 	u32 day1, day2, time;
-	u32 reg;
-	int err, tim, i = 0;
-
-	if (!slave) {
-		/* FIXME: Verify the max SCK rate */
-		slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
-				CONFIG_MC13783_SPI_CS, 1000000,
-				SPI_MODE_2 | SPI_CS_HIGH);
-		if (!slave)
-			return -1;
-	}
-
-	if (spi_claim_bus(slave))
-		return -1;
+	int tim, i = 0;
 
 	do {
-		reg = 0x2c000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
-				SPI_XFER_BEGIN | SPI_XFER_END);
-
-		if (err)
-			return err;
-
-		reg = 0x28000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
-				SPI_XFER_BEGIN | SPI_XFER_END);
+		day1 = pmic_reg_read(REG_RTC_DAY);
+		if (day1 < 0)
+			return -1;
 
-		if (err)
-			return err;
+		time = pmic_reg_read(REG_RTC_TIME);
+		if (time < 0)
+			return -1;
 
-		reg = 0x2c000000;
-		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
-				SPI_XFER_BEGIN | SPI_XFER_END);
+		day2 = pmic_reg_read(REG_RTC_DAY);
+		if (day2 < 0)
+			return -1;
 
-		if (err)
-			return err;
 	} while (day1 != day2 && i++ < 3);
 
-	spi_release_bus(slave);
-
 	tim = day1 * 86400 + time;
+
 	to_tm(tim, rtc);
 
 	rtc->tm_yday = 0;
@@ -80,34 +57,15 @@ int rtc_get(struct rtc_time *rtc)
 
 int rtc_set(struct rtc_time *rtc)
 {
-	u32 time, day, reg;
-
-	if (!slave) {
-		/* FIXME: Verify the max SCK rate */
-		slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
-				CONFIG_MC13783_SPI_CS, 1000000,
-				SPI_MODE_2 | SPI_CS_HIGH);
-		if (!slave)
-			return -1;
-	}
+	u32 time, day;
 
 	time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
 		      rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
 	day = time / 86400;
 	time %= 86400;
 
-	if (spi_claim_bus(slave))
-		return -1;
-
-	reg = 0x2c000000 | day | 0x80000000;
-	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day,
-			SPI_XFER_BEGIN | SPI_XFER_END);
-
-	reg = 0x28000000 | time | 0x80000000;
-	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
-			SPI_XFER_BEGIN | SPI_XFER_END);
-
-	spi_release_bus(slave);
+	pmic_reg_write(REG_RTC_DAY, day);
+	pmic_reg_write(REG_RTC_TIME, time);
 
 	return 0;
 }
diff --git a/include/configs/imx31_litekit.h b/include/configs/imx31_litekit.h
index 6131008..c025890 100644
--- a/include/configs/imx31_litekit.h
+++ b/include/configs/imx31_litekit.h
@@ -68,10 +68,13 @@
 #define CONFIG_DEFAULT_SPI_BUS	1
 #define CONFIG_DEFAULT_SPI_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
 
+#define CONFIG_FSL_PMIC
+#define CONFIG_FSL_PMIC_BUS	1
+#define CONFIG_FSL_PMIC_CS	0
+#define CONFIG_FSL_PMIC_CLK	1000000
+#define CONFIG_FSL_PMIC_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
+
 #define CONFIG_RTC_MC13783	1
-/* MC13783 connected to CSPI2 and SS0 */
-#define CONFIG_MC13783_SPI_BUS	1
-#define CONFIG_MC13783_SPI_CS	0
 
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
diff --git a/include/configs/mx31ads.h b/include/configs/mx31ads.h
index ec1c905..dedecd7 100644
--- a/include/configs/mx31ads.h
+++ b/include/configs/mx31ads.h
@@ -65,10 +65,12 @@
 #define CONFIG_DEFAULT_SPI_BUS	1
 #define CONFIG_DEFAULT_SPI_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
 
+#define CONFIG_FSL_PMIC
+#define CONFIG_FSL_PMIC_BUS	1
+#define CONFIG_FSL_PMIC_CS	0
+#define CONFIG_FSL_PMIC_CLK	1000000
+#define CONFIG_FSL_PMIC_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
 #define CONFIG_RTC_MC13783	1
-/* MC13783 connected to CSPI2 and SS0 */
-#define CONFIG_MC13783_SPI_BUS	1
-#define CONFIG_MC13783_SPI_CS	0
 
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
diff --git a/include/configs/mx31pdk.h b/include/configs/mx31pdk.h
index bee2f45..0414cc3 100644
--- a/include/configs/mx31pdk.h
+++ b/include/configs/mx31pdk.h
@@ -69,12 +69,13 @@
 #define CONFIG_DEFAULT_SPI_BUS	1
 #define CONFIG_DEFAULT_SPI_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
 
+#define CONFIG_FSL_PMIC
+#define CONFIG_FSL_PMIC_BUS	1
+#define CONFIG_FSL_PMIC_CS	2
+#define CONFIG_FSL_PMIC_CLK	1000000
+#define CONFIG_FSL_PMIC_MODE	(SPI_MODE_2 | SPI_CS_HIGH)
 #define CONFIG_RTC_MC13783	1
 
-/* MC13783 connected to CSPI2 and SS2 */
-#define CONFIG_MC13783_SPI_BUS	1
-#define CONFIG_MC13783_SPI_CS	2
-
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_CONS_INDEX		1
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V3 4/6] SPI: added support for MX51 to mxc_spi
  2010-03-16 16:18 [U-Boot] [PATCH] Added MC13892VK Power Management driver Stefano Babic
                   ` (2 preceding siblings ...)
  2010-04-19 21:04 ` [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
@ 2010-04-19 21:06 ` Stefano Babic
  3 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2010-04-19 21:06 UTC (permalink / raw)
  To: u-boot

This patch add SPI support for the MX51 processor.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

Changes: line errouneously removed before submitting the patch
(Thanks Magnus Lilja to point out the mistake).

 drivers/spi/mxc_spi.c |  230 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 210 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 3a45200..dd465f9 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -31,7 +31,7 @@
 #error "i.MX27 CSPI not supported due to drastic differences in register definisions" \
 "See linux mxc_spi driver from Freescale for details."
 
-#else
+#elif defined(CONFIG_MX31)
 
 #include <asm/arch/mx31.h>
 
@@ -56,6 +56,9 @@
 #define MXC_CSPICTRL_CHIPSELECT(x)	(((x) & 0x3) << 24)
 #define MXC_CSPICTRL_BITCOUNT(x)	(((x) & 0x1f) << 8)
 #define MXC_CSPICTRL_DATARATE(x)	(((x) & 0x7) << 16)
+#define MXC_CSPICTRL_TC		(1 << 8)
+#define MXC_CSPICTRL_RXOVF	(1 << 6)
+#define MXC_CSPICTRL_MAXBITS	0x1f
 
 #define MXC_CSPIPERIOD_32KHZ	(1 << 15)
 
@@ -65,12 +68,63 @@ static unsigned long spi_bases[] = {
 	0x53f84000,
 };
 
+#define OUT	MX31_GPIO_DIRECTION_OUT
+#define mxc_gpio_direction	mx31_gpio_direction
+#define mxc_gpio_set		mx31_gpio_set
+#elif defined(CONFIG_MX51)
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#define MXC_CSPIRXDATA		0x00
+#define MXC_CSPITXDATA		0x04
+#define MXC_CSPICTRL		0x08
+#define MXC_CSPICON		0x0C
+#define MXC_CSPIINT		0x10
+#define MXC_CSPIDMA		0x14
+#define MXC_CSPISTAT		0x18
+#define MXC_CSPIPERIOD		0x1C
+#define MXC_CSPIRESET		0x00
+#define MXC_CSPICTRL_EN		(1 << 0)
+#define MXC_CSPICTRL_MODE	(1 << 1)
+#define MXC_CSPICTRL_XCH	(1 << 2)
+#define MXC_CSPICTRL_CHIPSELECT(x)	(((x) & 0x3) << 12)
+#define MXC_CSPICTRL_BITCOUNT(x)	(((x) & 0xfff) << 20)
+#define MXC_CSPICTRL_PREDIV(x)	(((x) & 0xF) << 12)
+#define MXC_CSPICTRL_POSTDIV(x)	(((x) & 0xF) << 8)
+#define MXC_CSPICTRL_SELCHAN(x)	(((x) & 0x3) << 18)
+#define MXC_CSPICTRL_MAXBITS	0xfff
+#define MXC_CSPICTRL_TC		(1 << 7)
+#define MXC_CSPICTRL_RXOVF	(1 << 6)
+
+#define MXC_CSPIPERIOD_32KHZ	(1 << 15)
+
+/* Bit position inside CTRL register to be associated with SS */
+#define MXC_CSPICTRL_CHAN	18
+
+/* Bit position inside CON register to be associated with SS */
+#define MXC_CSPICON_POL		4
+#define MXC_CSPICON_PHA		0
+#define MXC_CSPICON_SSPOL	12
+
+static unsigned long spi_bases[] = {
+	CSPI1_BASE_ADDR,
+	CSPI2_BASE_ADDR,
+	CSPI3_BASE_ADDR,
+};
+#define mxc_gpio_direction(gpio, dir)	(0)
+#define mxc_gpio_set(gpio, value)	{}
+#define OUT	1
+#else
+#error "Unsupported architecture"
 #endif
 
 struct mxc_spi_slave {
 	struct spi_slave slave;
 	unsigned long	base;
 	u32		ctrl_reg;
+#if defined(CONFIG_MX51)
+	u32		cfg_reg;
+#endif
 	int		gpio;
 };
 
@@ -89,34 +143,161 @@ static inline void reg_write(unsigned long addr, u32 val)
 	*(volatile unsigned long*)addr = val;
 }
 
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+	if (mxcs->gpio > 0)
+		mxc_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+	if (mxcs->gpio > 0)
+		mxc_gpio_set(mxcs->gpio,
+			      !(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
+}
+
+#ifdef CONFIG_MX51
+static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
+	s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
+	u32 ss_pol = 0, sclkpol = 0, sclkpha = 0;
+
+	if (max_hz == 0) {
+		printf("Error: desired clock is 0\n");
+		return -1;
+	}
+
+	reg_ctrl = reg_read(mxcs->base + MXC_CSPICTRL);
+
+	/* Reset spi */
+	reg_write(mxcs->base + MXC_CSPICTRL, 0);
+	reg_write(mxcs->base + MXC_CSPICTRL, (reg_ctrl | 0x1));
+
+	/*
+	 * The following computation is taken directly from Freescale's code.
+	 */
+	if (clk_src > max_hz) {
+		pre_div = clk_src / max_hz;
+		if (pre_div > 16) {
+			post_div = pre_div / 16;
+			pre_div = 15;
+		}
+		if (post_div != 0) {
+			for (i = 0; i < 16; i++) {
+				if ((1 << i) >= post_div)
+					break;
+			}
+			if (i == 16) {
+				printf("Error: no divider for the freq: %d\n",
+					max_hz);
+				return -1;
+			}
+			post_div = i;
+		}
+	}
+
+	debug("pre_div = %d, post_div=%d\n", pre_div, post_div);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_SELCHAN(3)) |
+		MXC_CSPICTRL_SELCHAN(cs);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_PREDIV(0x0F)) |
+		MXC_CSPICTRL_PREDIV(pre_div);
+	reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
+		MXC_CSPICTRL_POSTDIV(post_div);
+
+	/* always set to master mode */
+	reg_ctrl |= 1 << (cs + 4);
+
+	/* We need to disable SPI before changing registers */
+	reg_ctrl &= ~MXC_CSPICTRL_EN;
+
+	if (mode & SPI_CS_HIGH)
+		ss_pol = 1;
+
+	if (!(mode & SPI_CPOL))
+		sclkpol = 1;
+
+	if (mode & SPI_CPHA)
+		sclkpha = 1;
+
+	reg_config = reg_read(mxcs->base + MXC_CSPICON);
+
+	/*
+	 * Configuration register setup
+	 * The MX51 has support different setup for each SS
+	 */
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
+		(ss_pol << (cs + MXC_CSPICON_SSPOL));
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_POL))) |
+		(sclkpol << (cs + MXC_CSPICON_POL));
+	reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_PHA))) |
+		(sclkpha << (cs + MXC_CSPICON_PHA));
+
+	debug("reg_ctrl = 0x%x\n", reg_ctrl);
+	reg_write(mxcs->base + MXC_CSPICTRL, reg_ctrl);
+	debug("reg_config = 0x%x\n", reg_config);
+	reg_write(mxcs->base + MXC_CSPICON, reg_config);
+
+	/* save config register and control register */
+	mxcs->ctrl_reg = reg_ctrl;
+	mxcs->cfg_reg = reg_config;
+
+	/* clear interrupt reg */
+	reg_write(mxcs->base + MXC_CSPIINT, 0);
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+	return 0;
+}
+#endif
+
 static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
 			   unsigned long flags)
 {
 	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL);
 
-	mxcs->ctrl_reg = (mxcs->ctrl_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
+	if (flags & SPI_XFER_BEGIN)
+		spi_cs_activate(slave);
+
+	mxcs->ctrl_reg = (mxcs->ctrl_reg &
+		~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
 		MXC_CSPICTRL_BITCOUNT(bitlen - 1);
 
-	if (cfg_reg != mxcs->ctrl_reg)
-		reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
+	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
+#ifdef CONFIG_MX51
+	reg_write(mxcs->base + MXC_CSPICON, mxcs->cfg_reg);
+#endif
 
-	if (mxcs->gpio > 0 && (flags & SPI_XFER_BEGIN))
-		mx31_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
+	/* Clear interrupt register */
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 
+	debug("Sending SPI 0x%x\n", data);
 	reg_write(mxcs->base + MXC_CSPITXDATA, data);
 
-	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_XCH);
+	/* FIFO is written, now starts the transfer setting the XCH bit */
+	reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg |
+		MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
 
-	while (reg_read(mxcs->base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH)
+	/* Wait until the TC (Transfer completed) bit is set */
+	while ((reg_read(mxcs->base + MXC_CSPISTAT) & MXC_CSPICTRL_TC) == 0)
 		;
 
-	if (mxcs->gpio > 0 && (flags & SPI_XFER_END)) {
-		mx31_gpio_set(mxcs->gpio,
-			      !(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
-	}
+	/* Transfer completed, clear any pending request */
+	reg_write(mxcs->base + MXC_CSPISTAT,
+		MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+	data = reg_read(mxcs->base + MXC_CSPIRXDATA);
+	debug("SPI Rx: 0x%x\n", data);
+
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	return data;
 
-	return reg_read(mxcs->base + MXC_CSPIRXDATA);
 }
 
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
@@ -176,7 +357,7 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
 	if (cs > 3) {
 		mxcs->gpio = cs >> 8;
 		cs &= 3;
-		ret = mx31_gpio_direction(mxcs->gpio, MX31_GPIO_DIRECTION_OUT);
+		ret = mxc_gpio_direction(mxcs->gpio, OUT);
 		if (ret) {
 			printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
 			return -EINVAL;
@@ -210,6 +391,19 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
 	cs = ret;
 
+	mxcs->slave.bus = bus;
+	mxcs->slave.cs = cs;
+	mxcs->base = spi_bases[bus];
+
+#ifdef CONFIG_MX51
+	/* Can be used for i.MX31 too ? */
+	ret = spi_cfg(mxcs, cs, max_hz, mode);
+	if (ret) {
+		printf("mxc_spi: cannot setup SPI controller\n");
+		free(mxcs);
+		return NULL;
+	}
+#else
 	ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
 		MXC_CSPICTRL_BITCOUNT(31) |
 		MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */
@@ -222,12 +416,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		ctrl_reg |= MXC_CSPICTRL_POL;
 	if (mode & SPI_CS_HIGH)
 		ctrl_reg |= MXC_CSPICTRL_SSPOL;
-
-	mxcs->slave.bus = bus;
-	mxcs->slave.cs = cs;
-	mxcs->base = spi_bases[bus];
 	mxcs->ctrl_reg = ctrl_reg;
-
+#endif
 	return &mxcs->slave;
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC
  2010-04-19 21:04 ` [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
@ 2010-04-22 20:06   ` Magnus Lilja
  2010-04-23  8:19     ` Stefano Babic
  0 siblings, 1 reply; 15+ messages in thread
From: Magnus Lilja @ 2010-04-22 20:06 UTC (permalink / raw)
  To: u-boot

Hi

On 04/19/2010 11:04 PM, Stefano Babic wrote:
> The RTC is part of the Freescale's PMIC controller.
> Use general function to access to PMIC internal registers.
> 
> Signed-off-by: Stefano Babic <sbabic@denx.de>
> ---
> 
> Changes since last version: configuration of the RTC must be
> updated for the boards that are using it.

I've compiled and tested this on i.MX31 Litekit and it seems to work. I suspect it works on the PDK board as well but I
haven't actually tried that yet.

Regards, Magnus

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC
  2010-04-22 20:06   ` Magnus Lilja
@ 2010-04-23  8:19     ` Stefano Babic
  0 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2010-04-23  8:19 UTC (permalink / raw)
  To: u-boot

Magnus Lilja wrote:
> Hi

Hi Magnus,

> I've compiled and tested this on i.MX31 Litekit and it seems to work.
> I suspect it works on the PDK board as well but I haven't actually
> tried that yet.

Thanks for testing.

Regards,
Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2010-04-23  8:19 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-16 16:18 [U-Boot] [PATCH] Added MC13892VK Power Management driver Stefano Babic
2010-03-20 23:55 ` Tom
2010-03-22 10:21   ` Stefano Babic
2010-04-19  7:56 ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Stefano Babic
2010-04-19  7:56   ` [U-Boot] [PATCH 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
2010-04-19  7:56     ` [U-Boot] [PATCH 3/6] MX31: Add support for PMIC to the QONG module Stefano Babic
2010-04-19  7:56       ` [U-Boot] [PATCH V2 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic
2010-04-19  7:56         ` [U-Boot] [PATCH 5/6] MX: Added definition file for MC13892 Stefano Babic
2010-04-19  7:57           ` [U-Boot] [PATCH V2 6/6] Add SPI support to mx51evk board Stefano Babic
2010-04-19 18:42   ` [U-Boot] [PATCH 1/6] MX: Added Freescale Power Management Driver Magnus Lilja
2010-04-19 20:10     ` Stefano Babic
2010-04-19 21:04 ` [U-Boot] [PATCH V2 2/6] MX: RTC13783 uses general function to access PMIC Stefano Babic
2010-04-22 20:06   ` Magnus Lilja
2010-04-23  8:19     ` Stefano Babic
2010-04-19 21:06 ` [U-Boot] [PATCH V3 4/6] SPI: added support for MX51 to mxc_spi Stefano Babic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.