* [PATCH 0/8] A bit of new code and sparse cleanups along the way
@ 2008-03-11 17:21 Anton Vorontsov
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
` (8 more replies)
0 siblings, 9 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:21 UTC (permalink / raw)
To: linuxppc-dev
Hi all,
Please consider these patches for the 2.6.26.
Thanks,
--
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
@ 2008-03-11 17:23 ` Anton Vorontsov
2008-04-11 14:06 ` Kumar Gala
2008-04-14 15:10 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs Anton Vorontsov
` (7 subsequent siblings)
8 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:23 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-mtd
This is needed to support other localbus peripherals, such as
NAND on FSL UPM.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Would be great if someone from the MTD community will ack this patch
to go through powerpc trees.
Thanks,
drivers/mtd/nand/fsl_elbc_nand.c | 219 ++-----------------------------------
include/asm-powerpc/fsl_lbc.h | 223 ++++++++++++++++++++++++++++++++++++++
2 files changed, 235 insertions(+), 207 deletions(-)
create mode 100644 include/asm-powerpc/fsl_lbc.h
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index b025dfe..378b7aa 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -36,207 +36,12 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-
+#include <asm/fsl_lbc.h>
#define MAX_BANKS 8
#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
-struct elbc_bank {
- __be32 br; /**< Base Register */
-#define BR_BA 0xFFFF8000
-#define BR_BA_SHIFT 15
-#define BR_PS 0x00001800
-#define BR_PS_SHIFT 11
-#define BR_PS_8 0x00000800 /* Port Size 8 bit */
-#define BR_PS_16 0x00001000 /* Port Size 16 bit */
-#define BR_PS_32 0x00001800 /* Port Size 32 bit */
-#define BR_DECC 0x00000600
-#define BR_DECC_SHIFT 9
-#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
-#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
-#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
-#define BR_WP 0x00000100
-#define BR_WP_SHIFT 8
-#define BR_MSEL 0x000000E0
-#define BR_MSEL_SHIFT 5
-#define BR_MS_GPCM 0x00000000 /* GPCM */
-#define BR_MS_FCM 0x00000020 /* FCM */
-#define BR_MS_SDRAM 0x00000060 /* SDRAM */
-#define BR_MS_UPMA 0x00000080 /* UPMA */
-#define BR_MS_UPMB 0x000000A0 /* UPMB */
-#define BR_MS_UPMC 0x000000C0 /* UPMC */
-#define BR_V 0x00000001
-#define BR_V_SHIFT 0
-#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
-
- __be32 or; /**< Base Register */
-#define OR0 0x5004
-#define OR1 0x500C
-#define OR2 0x5014
-#define OR3 0x501C
-#define OR4 0x5024
-#define OR5 0x502C
-#define OR6 0x5034
-#define OR7 0x503C
-
-#define OR_FCM_AM 0xFFFF8000
-#define OR_FCM_AM_SHIFT 15
-#define OR_FCM_BCTLD 0x00001000
-#define OR_FCM_BCTLD_SHIFT 12
-#define OR_FCM_PGS 0x00000400
-#define OR_FCM_PGS_SHIFT 10
-#define OR_FCM_CSCT 0x00000200
-#define OR_FCM_CSCT_SHIFT 9
-#define OR_FCM_CST 0x00000100
-#define OR_FCM_CST_SHIFT 8
-#define OR_FCM_CHT 0x00000080
-#define OR_FCM_CHT_SHIFT 7
-#define OR_FCM_SCY 0x00000070
-#define OR_FCM_SCY_SHIFT 4
-#define OR_FCM_SCY_1 0x00000010
-#define OR_FCM_SCY_2 0x00000020
-#define OR_FCM_SCY_3 0x00000030
-#define OR_FCM_SCY_4 0x00000040
-#define OR_FCM_SCY_5 0x00000050
-#define OR_FCM_SCY_6 0x00000060
-#define OR_FCM_SCY_7 0x00000070
-#define OR_FCM_RST 0x00000008
-#define OR_FCM_RST_SHIFT 3
-#define OR_FCM_TRLX 0x00000004
-#define OR_FCM_TRLX_SHIFT 2
-#define OR_FCM_EHTR 0x00000002
-#define OR_FCM_EHTR_SHIFT 1
-};
-
-struct elbc_regs {
- struct elbc_bank bank[8];
- u8 res0[0x28];
- __be32 mar; /**< UPM Address Register */
- u8 res1[0x4];
- __be32 mamr; /**< UPMA Mode Register */
- __be32 mbmr; /**< UPMB Mode Register */
- __be32 mcmr; /**< UPMC Mode Register */
- u8 res2[0x8];
- __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
- __be32 mdr; /**< UPM Data Register */
- u8 res3[0x4];
- __be32 lsor; /**< Special Operation Initiation Register */
- __be32 lsdmr; /**< SDRAM Mode Register */
- u8 res4[0x8];
- __be32 lurt; /**< UPM Refresh Timer */
- __be32 lsrt; /**< SDRAM Refresh Timer */
- u8 res5[0x8];
- __be32 ltesr; /**< Transfer Error Status Register */
-#define LTESR_BM 0x80000000
-#define LTESR_FCT 0x40000000
-#define LTESR_PAR 0x20000000
-#define LTESR_WP 0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS 0x00080000
-#define LTESR_CC 0x00000001
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
- __be32 ltedr; /**< Transfer Error Disable Register */
- __be32 lteir; /**< Transfer Error Interrupt Register */
- __be32 lteatr; /**< Transfer Error Attributes Register */
- __be32 ltear; /**< Transfer Error Address Register */
- u8 res6[0xC];
- __be32 lbcr; /**< Configuration Register */
-#define LBCR_LDIS 0x80000000
-#define LBCR_LDIS_SHIFT 31
-#define LBCR_BCTLC 0x00C00000
-#define LBCR_BCTLC_SHIFT 22
-#define LBCR_AHD 0x00200000
-#define LBCR_LPBSE 0x00020000
-#define LBCR_LPBSE_SHIFT 17
-#define LBCR_EPAR 0x00010000
-#define LBCR_EPAR_SHIFT 16
-#define LBCR_BMT 0x0000FF00
-#define LBCR_BMT_SHIFT 8
-#define LBCR_INIT 0x00040000
- __be32 lcrr; /**< Clock Ratio Register */
-#define LCRR_DBYP 0x80000000
-#define LCRR_DBYP_SHIFT 31
-#define LCRR_BUFCMDC 0x30000000
-#define LCRR_BUFCMDC_SHIFT 28
-#define LCRR_ECL 0x03000000
-#define LCRR_ECL_SHIFT 24
-#define LCRR_EADC 0x00030000
-#define LCRR_EADC_SHIFT 16
-#define LCRR_CLKDIV 0x0000000F
-#define LCRR_CLKDIV_SHIFT 0
- u8 res7[0x8];
- __be32 fmr; /**< Flash Mode Register */
-#define FMR_CWTO 0x0000F000
-#define FMR_CWTO_SHIFT 12
-#define FMR_BOOT 0x00000800
-#define FMR_ECCM 0x00000100
-#define FMR_AL 0x00000030
-#define FMR_AL_SHIFT 4
-#define FMR_OP 0x00000003
-#define FMR_OP_SHIFT 0
- __be32 fir; /**< Flash Instruction Register */
-#define FIR_OP0 0xF0000000
-#define FIR_OP0_SHIFT 28
-#define FIR_OP1 0x0F000000
-#define FIR_OP1_SHIFT 24
-#define FIR_OP2 0x00F00000
-#define FIR_OP2_SHIFT 20
-#define FIR_OP3 0x000F0000
-#define FIR_OP3_SHIFT 16
-#define FIR_OP4 0x0000F000
-#define FIR_OP4_SHIFT 12
-#define FIR_OP5 0x00000F00
-#define FIR_OP5_SHIFT 8
-#define FIR_OP6 0x000000F0
-#define FIR_OP6_SHIFT 4
-#define FIR_OP7 0x0000000F
-#define FIR_OP7_SHIFT 0
-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
-#define FIR_OP_CA 0x1 /* Issue current column address */
-#define FIR_OP_PA 0x2 /* Issue current block+page address */
-#define FIR_OP_UA 0x3 /* Issue user defined address */
-#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
-#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
-#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
-#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
-#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
- __be32 fcr; /**< Flash Command Register */
-#define FCR_CMD0 0xFF000000
-#define FCR_CMD0_SHIFT 24
-#define FCR_CMD1 0x00FF0000
-#define FCR_CMD1_SHIFT 16
-#define FCR_CMD2 0x0000FF00
-#define FCR_CMD2_SHIFT 8
-#define FCR_CMD3 0x000000FF
-#define FCR_CMD3_SHIFT 0
- __be32 fbar; /**< Flash Block Address Register */
-#define FBAR_BLK 0x00FFFFFF
- __be32 fpar; /**< Flash Page Address Register */
-#define FPAR_SP_PI 0x00007C00
-#define FPAR_SP_PI_SHIFT 10
-#define FPAR_SP_MS 0x00000200
-#define FPAR_SP_CI 0x000001FF
-#define FPAR_SP_CI_SHIFT 0
-#define FPAR_LP_PI 0x0003F000
-#define FPAR_LP_PI_SHIFT 12
-#define FPAR_LP_MS 0x00000800
-#define FPAR_LP_CI 0x000007FF
-#define FPAR_LP_CI_SHIFT 0
- __be32 fbcr; /**< Flash Byte Count Register */
-#define FBCR_BC 0x00000FFF
- u8 res11[0x8];
- u8 res8[0xF00];
-};
-
struct fsl_elbc_ctrl;
/* mtd information per set */
@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
/* device info */
struct device *dev;
- struct elbc_regs __iomem *regs;
+ struct fsl_lbc_regs __iomem *regs;
int irq;
wait_queue_head_t irq_wait;
unsigned int irq_status; /* status read from LTESR by irq handler */
@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
int buf_num;
ctrl->page = page_addr;
@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* Setup the FMR[OP] to execute without write protection */
out_be32(&lbc->fmr, priv->fmr | 3);
@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (priv->page_size) {
out_be32(&lbc->fir,
@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
ctrl->use_mdr = 0;
@@ -775,7 +580,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
@@ -807,7 +612,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
/* calculate FMR Address Length field */
@@ -922,7 +727,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
{
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct nand_chip *chip = &priv->chip;
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -986,7 +791,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
struct device_node *node)
{
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct fsl_elbc_mtd *priv;
struct resource res;
#ifdef CONFIG_MTD_PARTITIONS
@@ -1083,7 +888,7 @@ err:
static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
{
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* clear event registers */
setbits32(&lbc->ltesr, LTESR_NAND_MASK);
@@ -1128,7 +933,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
{
struct fsl_elbc_ctrl *ctrl = data;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
if (status) {
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
new file mode 100644
index 0000000..13a3c28
--- /dev/null
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -0,0 +1,223 @@
+/* Freescale Local Bus Controller
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ * Scott Wood <scottwood@freescale.com>
+ *
+ * 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 __ASM_FSL_LBC_H
+#define __ASM_FSL_LBC_H
+
+#include <linux/types.h>
+
+struct fsl_lbc_bank {
+ __be32 br; /**< Base Register */
+#define BR_BA 0xFFFF8000
+#define BR_BA_SHIFT 15
+#define BR_PS 0x00001800
+#define BR_PS_SHIFT 11
+#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+#define BR_DECC 0x00000600
+#define BR_DECC_SHIFT 9
+#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
+#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
+#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
+#define BR_WP 0x00000100
+#define BR_WP_SHIFT 8
+#define BR_MSEL 0x000000E0
+#define BR_MSEL_SHIFT 5
+#define BR_MS_GPCM 0x00000000 /* GPCM */
+#define BR_MS_FCM 0x00000020 /* FCM */
+#define BR_MS_SDRAM 0x00000060 /* SDRAM */
+#define BR_MS_UPMA 0x00000080 /* UPMA */
+#define BR_MS_UPMB 0x000000A0 /* UPMB */
+#define BR_MS_UPMC 0x000000C0 /* UPMC */
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+
+ __be32 or; /**< Base Register */
+#define OR0 0x5004
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_FCM_AM 0xFFFF8000
+#define OR_FCM_AM_SHIFT 15
+#define OR_FCM_BCTLD 0x00001000
+#define OR_FCM_BCTLD_SHIFT 12
+#define OR_FCM_PGS 0x00000400
+#define OR_FCM_PGS_SHIFT 10
+#define OR_FCM_CSCT 0x00000200
+#define OR_FCM_CSCT_SHIFT 9
+#define OR_FCM_CST 0x00000100
+#define OR_FCM_CST_SHIFT 8
+#define OR_FCM_CHT 0x00000080
+#define OR_FCM_CHT_SHIFT 7
+#define OR_FCM_SCY 0x00000070
+#define OR_FCM_SCY_SHIFT 4
+#define OR_FCM_SCY_1 0x00000010
+#define OR_FCM_SCY_2 0x00000020
+#define OR_FCM_SCY_3 0x00000030
+#define OR_FCM_SCY_4 0x00000040
+#define OR_FCM_SCY_5 0x00000050
+#define OR_FCM_SCY_6 0x00000060
+#define OR_FCM_SCY_7 0x00000070
+#define OR_FCM_RST 0x00000008
+#define OR_FCM_RST_SHIFT 3
+#define OR_FCM_TRLX 0x00000004
+#define OR_FCM_TRLX_SHIFT 2
+#define OR_FCM_EHTR 0x00000002
+#define OR_FCM_EHTR_SHIFT 1
+};
+
+struct fsl_lbc_regs {
+ struct fsl_lbc_bank bank[8];
+ u8 res0[0x28];
+ __be32 mar; /**< UPM Address Register */
+ u8 res1[0x4];
+ __be32 mamr; /**< UPMA Mode Register */
+ __be32 mbmr; /**< UPMB Mode Register */
+ __be32 mcmr; /**< UPMC Mode Register */
+ u8 res2[0x8];
+ __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
+ __be32 mdr; /**< UPM Data Register */
+ u8 res3[0x4];
+ __be32 lsor; /**< Special Operation Initiation Register */
+ __be32 lsdmr; /**< SDRAM Mode Register */
+ u8 res4[0x8];
+ __be32 lurt; /**< UPM Refresh Timer */
+ __be32 lsrt; /**< SDRAM Refresh Timer */
+ u8 res5[0x8];
+ __be32 ltesr; /**< Transfer Error Status Register */
+#define LTESR_BM 0x80000000
+#define LTESR_FCT 0x40000000
+#define LTESR_PAR 0x20000000
+#define LTESR_WP 0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS 0x00080000
+#define LTESR_CC 0x00000001
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+ __be32 ltedr; /**< Transfer Error Disable Register */
+ __be32 lteir; /**< Transfer Error Interrupt Register */
+ __be32 lteatr; /**< Transfer Error Attributes Register */
+ __be32 ltear; /**< Transfer Error Address Register */
+ u8 res6[0xC];
+ __be32 lbcr; /**< Configuration Register */
+#define LBCR_LDIS 0x80000000
+#define LBCR_LDIS_SHIFT 31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT 22
+#define LBCR_AHD 0x00200000
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT 17
+#define LBCR_EPAR 0x00010000
+#define LBCR_EPAR_SHIFT 16
+#define LBCR_BMT 0x0000FF00
+#define LBCR_BMT_SHIFT 8
+#define LBCR_INIT 0x00040000
+ __be32 lcrr; /**< Clock Ratio Register */
+#define LCRR_DBYP 0x80000000
+#define LCRR_DBYP_SHIFT 31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT 28
+#define LCRR_ECL 0x03000000
+#define LCRR_ECL_SHIFT 24
+#define LCRR_EADC 0x00030000
+#define LCRR_EADC_SHIFT 16
+#define LCRR_CLKDIV 0x0000000F
+#define LCRR_CLKDIV_SHIFT 0
+ u8 res7[0x8];
+ __be32 fmr; /**< Flash Mode Register */
+#define FMR_CWTO 0x0000F000
+#define FMR_CWTO_SHIFT 12
+#define FMR_BOOT 0x00000800
+#define FMR_ECCM 0x00000100
+#define FMR_AL 0x00000030
+#define FMR_AL_SHIFT 4
+#define FMR_OP 0x00000003
+#define FMR_OP_SHIFT 0
+ __be32 fir; /**< Flash Instruction Register */
+#define FIR_OP0 0xF0000000
+#define FIR_OP0_SHIFT 28
+#define FIR_OP1 0x0F000000
+#define FIR_OP1_SHIFT 24
+#define FIR_OP2 0x00F00000
+#define FIR_OP2_SHIFT 20
+#define FIR_OP3 0x000F0000
+#define FIR_OP3_SHIFT 16
+#define FIR_OP4 0x0000F000
+#define FIR_OP4_SHIFT 12
+#define FIR_OP5 0x00000F00
+#define FIR_OP5_SHIFT 8
+#define FIR_OP6 0x000000F0
+#define FIR_OP6_SHIFT 4
+#define FIR_OP7 0x0000000F
+#define FIR_OP7_SHIFT 0
+#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+#define FIR_OP_CA 0x1 /* Issue current column address */
+#define FIR_OP_PA 0x2 /* Issue current block+page address */
+#define FIR_OP_UA 0x3 /* Issue user defined address */
+#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
+ __be32 fcr; /**< Flash Command Register */
+#define FCR_CMD0 0xFF000000
+#define FCR_CMD0_SHIFT 24
+#define FCR_CMD1 0x00FF0000
+#define FCR_CMD1_SHIFT 16
+#define FCR_CMD2 0x0000FF00
+#define FCR_CMD2_SHIFT 8
+#define FCR_CMD3 0x000000FF
+#define FCR_CMD3_SHIFT 0
+ __be32 fbar; /**< Flash Block Address Register */
+#define FBAR_BLK 0x00FFFFFF
+ __be32 fpar; /**< Flash Page Address Register */
+#define FPAR_SP_PI 0x00007C00
+#define FPAR_SP_PI_SHIFT 10
+#define FPAR_SP_MS 0x00000200
+#define FPAR_SP_CI 0x000001FF
+#define FPAR_SP_CI_SHIFT 0
+#define FPAR_LP_PI 0x0003F000
+#define FPAR_LP_PI_SHIFT 12
+#define FPAR_LP_MS 0x00000800
+#define FPAR_LP_CI 0x000007FF
+#define FPAR_LP_CI_SHIFT 0
+ __be32 fbcr; /**< Flash Byte Count Register */
+#define FBCR_BC 0x00000FFF
+ u8 res11[0x8];
+ u8 res8[0xF00];
+};
+
+#endif /* __ASM_FSL_LBC_H */
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-04-11 14:09 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset Anton Vorontsov
` (6 subsequent siblings)
8 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
These will be used by the FSL UPM NAND driver.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/Kconfig | 5 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 99 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/fsl_lbc.h | 63 ++++++++++++++++++++++++++
4 files changed, 168 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ef12db0..9c68592 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,6 +491,11 @@ config FSL_PCI
bool
select PPC_INDIRECT_PCI
+config FSL_LBC
+ bool
+ help
+ Freescale Localbus support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 15f3e85..62b6ef0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
+obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 0000000..b59f2f4
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,99 @@
+/*
+ * Freescale UPM routines.
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/fsl_lbc.h>
+
+spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+
+struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+EXPORT_SYMBOL(fsl_lbc_regs);
+
+static char __initdata *compat_lbc[] = {
+ "fsl,pq2-localbus",
+ "fsl,pq2pro-localbus",
+ "fsl,pq3-localbus",
+ "fsl,elbc",
+};
+
+static int __init fsl_lbc_init(void)
+{
+ struct device_node *lbus;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
+ lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
+ if (lbus)
+ goto found;
+ }
+ return -ENODEV;
+
+found:
+ fsl_lbc_regs = of_iomap(lbus, 0);
+ of_node_put(lbus);
+ if (!fsl_lbc_regs)
+ return -ENOMEM;
+ return 0;
+}
+arch_initcall(fsl_lbc_init);
+
+int fsl_upm_find(u32 base, struct fsl_upm *upm)
+{
+ int i;
+ __be32 br;
+ __be32 or;
+
+ if (!fsl_lbc_regs)
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
+ br = in_be32(&fsl_lbc_regs->bank[i].br);
+ or = in_be32(&fsl_lbc_regs->bank[i].or);
+
+ if (br & BR_V && (br & or & BR_BA) == base)
+ goto found;
+ }
+
+ return -ENOENT;
+found:
+ switch (br & BR_MSEL) {
+ case BR_MS_UPMA:
+ upm->mxmr = &fsl_lbc_regs->mamr;
+ break;
+ case BR_MS_UPMB:
+ upm->mxmr = &fsl_lbc_regs->mbmr;
+ break;
+ case BR_MS_UPMC:
+ upm->mxmr = &fsl_lbc_regs->mcmr;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (br & BR_PS) {
+ case BR_PS_8:
+ upm->width = 8;
+ break;
+ case BR_PS_16:
+ upm->width = 16;
+ break;
+ case BR_PS_32:
+ upm->width = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
index 13a3c28..a6b99a3 100644
--- a/include/asm-powerpc/fsl_lbc.h
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -24,6 +24,8 @@
#define __ASM_FSL_LBC_H
#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
struct fsl_lbc_bank {
__be32 br; /**< Base Register */
@@ -98,6 +100,11 @@ struct fsl_lbc_regs {
__be32 mar; /**< UPM Address Register */
u8 res1[0x4];
__be32 mamr; /**< UPMA Mode Register */
+#define MxMR_OP_NO (0 << 28) /**< normal operation */
+#define MxMR_OP_WA (1 << 28) /**< write array */
+#define MxMR_OP_RA (2 << 28) /**< read array */
+#define MxMR_OP_RP (3 << 28) /**< run pattern */
+#define MxMR_MAD 0x3f /**< machine address */
__be32 mbmr; /**< UPMB Mode Register */
__be32 mcmr; /**< UPMC Mode Register */
u8 res2[0x8];
@@ -220,4 +227,60 @@ struct fsl_lbc_regs {
u8 res8[0xF00];
};
+extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+extern spinlock_t fsl_lbc_lock;
+
+/*
+ * FSL UPM routines
+ */
+struct fsl_upm {
+ __be32 __iomem *mxmr;
+ int width;
+};
+
+extern int fsl_upm_find(u32 base, struct fsl_upm *upm);
+
+static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
+{
+ clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
+}
+
+static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
+{
+ clrbits32(upm->mxmr, MxMR_OP_RP);
+
+ while (in_be32(upm->mxmr) & MxMR_OP_RP)
+ cpu_relax();
+}
+
+static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
+ void __iomem *io_base, u32 mar)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+ out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+ switch (upm->width) {
+ case 8:
+ out_8(io_base, 0x0);
+ break;
+ case 16:
+ out_be16(io_base, 0x0);
+ break;
+ case 32:
+ out_be32(io_base, 0x0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+ return ret;
+}
+
#endif /* __ASM_FSL_LBC_H */
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
2008-03-11 17:24 ` [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-03-18 17:48 ` Scott Wood
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h Anton Vorontsov
` (5 subsequent siblings)
8 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
qe_muram_offset is the reverse of the qe_muram_addr, will be
used for the Freescale QE USB Host Controller driver.
This patch also moves qe_muram_addr into the qe.h header, plus
adds __iomem hints to use with sparse.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/qe.c | 8 +-------
include/asm-powerpc/immap_qe.h | 2 +-
include/asm-powerpc/qe.h | 11 ++++++++++-
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 6efbd5e..b444b1d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -55,7 +55,7 @@ struct qe_snum {
/* We allocate this here because it is used almost exclusively for
* the communication processor devices.
*/
-struct qe_immap *qe_immr = NULL;
+struct qe_immap __iomem *qe_immr;
EXPORT_SYMBOL(qe_immr);
static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
@@ -415,12 +415,6 @@ void qe_muram_dump(void)
}
EXPORT_SYMBOL(qe_muram_dump);
-void *qe_muram_addr(unsigned long offset)
-{
- return (void *)&qe_immr->muram[offset];
-}
-EXPORT_SYMBOL(qe_muram_addr);
-
/* The maximum number of RISCs we support */
#define MAX_QE_RISC 2
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 82a4526..924aefb 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -468,7 +468,7 @@ struct qe_immap {
u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
} __attribute__ ((packed));
-extern struct qe_immap *qe_immr;
+extern struct qe_immap __iomem *qe_immr;
extern phys_addr_t get_qe_base(void);
static inline unsigned long immrbar_virt_to_phys(void *address)
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 430dc77..398534c 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -92,7 +92,16 @@ unsigned long qe_muram_alloc(int size, int align);
int qe_muram_free(unsigned long offset);
unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
void qe_muram_dump(void);
-void *qe_muram_addr(unsigned long offset);
+
+static inline void __iomem *qe_muram_addr(unsigned long offset)
+{
+ return (void __iomem *)&qe_immr->muram[offset];
+}
+
+static inline unsigned long qe_muram_offset(void __iomem *addr)
+{
+ return addr - (void __iomem *)qe_immr->muram;
+}
/* Structure that defines QE firmware binary files.
*
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (2 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk() Anton Vorontsov
` (4 subsequent siblings)
8 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
Headers should include prototypes they use, otherwise build will
break if we use it without explicitly including io.h:
CC arch/powerpc/sysdev/qe_lib/gtm.o
In file included from include/asm/qe.h:20,
from arch/powerpc/sysdev/qe_lib/gtm.c:18:
include/asm/immap_qe.h: In function ‘immrbar_virt_to_phys’:
include/asm/immap_qe.h:480: error: implicit declaration of function ‘virt_to_phys’
make[2]: *** [arch/powerpc/sysdev/qe_lib/gtm.o] Error 1
make[1]: *** [arch/powerpc/sysdev/qe_lib] Error 2
gtm.c needs qe.h (which includes immap_qe.h) to use qe_get_brg_clk().
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
include/asm-powerpc/immap_qe.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 924aefb..7b6f411 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -20,6 +20,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
+#include <asm/io.h>
#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk()
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (3 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-03-11 18:36 ` Kumar Gala
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support Anton Vorontsov
` (3 subsequent siblings)
8 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
qe_get_brg_clk() will be used by the fsl_gtm routines.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/qe.c | 5 +++--
include/asm-powerpc/qe.h | 1 +
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index b444b1d..2061c46 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(qe_issue_cmd);
*/
static unsigned int brg_clk = 0;
-unsigned int get_brg_clk(void)
+unsigned int qe_get_brg_clk(void)
{
struct device_node *qe;
unsigned int size;
@@ -180,6 +180,7 @@ unsigned int get_brg_clk(void)
return brg_clk;
}
+EXPORT_SYMBOL(qe_get_brg_clk);
/* Program the BRG to the given sampling rate and multiplier
*
@@ -197,7 +198,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
if ((brg < QE_BRG1) || (brg > QE_BRG16))
return -EINVAL;
- divisor = get_brg_clk() / (rate * multiplier);
+ divisor = qe_get_brg_clk() / (rate * multiplier);
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
div16 = QE_BRGC_DIV16;
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 398534c..c3be6e2 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -85,6 +85,7 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
/* QE internal API */
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
enum qe_clock qe_clock_source(const char *source);
+unsigned int qe_get_brg_clk(void);
int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
int qe_get_snum(void);
void qe_put_snum(u8 snum);
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (4 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk() Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-03-18 17:43 ` Scott Wood
2008-04-08 9:01 ` Laurent Pinchart
2008-03-11 17:24 ` [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB Anton Vorontsov
` (2 subsequent siblings)
8 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts.
There are several limitations in this support:
1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
This is straightforward to implement when needed, two timers should
be marked as "requested" and configured as appropriate.
2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
This is also straightforward to implement when needed, all timers
should be marked as "requested" and configured as appropriate.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 27 +++-
arch/powerpc/Kconfig | 5 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_gtm.c | 263 ++++++++++++++++++++++++++
arch/powerpc/sysdev/qe_lib/Kconfig | 5 +
arch/powerpc/sysdev/qe_lib/Makefile | 1 +
arch/powerpc/sysdev/qe_lib/gtm.c | 47 +++++
include/asm-powerpc/fsl_gtm.h | 138 ++++++++++++++
8 files changed, 486 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 arch/powerpc/sysdev/qe_lib/gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 8ae57f2..b506245 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,8 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Freescale General-purpose Timers Module
VII - Specifying interrupt information for devices
1) interrupts property
@@ -2811,6 +2812,30 @@ platforms are moved over to use the flattened-device-tree model.
big-endian;
};
+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+ GTMs).
+ - reg : should contain gtm registers location and length (0x40).
+ - interrupts : should contain four interrupts.
+ - interrupt-parent : interrupt source phandle.
+
+ Example:
+
+ gtm@500 {
+ compatible = "fsl,gtm";
+ reg = <0x500 0x40>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ gtm@440 {
+ compatible = "fsl,qe-gtm", "fsl,gtm";
+ reg = <0x440 0x40>;
+ interrupts = <12 13 14 15>;
+ interrupt-parent = <&qeic>;
+ };
More devices will be defined as this spec matures.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9c68592..0b27cbd 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -496,6 +496,11 @@ config FSL_LBC
help
Freescale Localbus support
+config FSL_GTM
+ bool
+ help
+ Freescale General-purpose Timers support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 62b6ef0..a7e8da4 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
+obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
new file mode 100644
index 0000000..975fe4e
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,263 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <asm/fsl_gtm.h>
+
+struct gtm_timer *gtm_get_timer(int width)
+{
+ struct device_node *np;
+ struct gtm *gtm = NULL;
+ int i;
+
+ if (width != 16)
+ return ERR_PTR(-ENOSYS);
+
+ for_each_compatible_node(np, NULL, "fsl,gtm") {
+ if (!np->data) {
+ WARN_ON(1);
+ continue;
+ }
+ gtm = np->data;
+
+ spin_lock_irq(>m->lock);
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ if (!gtm->timers[i].requested) {
+ gtm->timers[i].requested = true;
+ spin_unlock_irq(>m->lock);
+ of_node_put(np);
+ return >m->timers[i];
+ }
+ }
+
+ spin_unlock_irq(>m->lock);
+ }
+
+ if (gtm)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);
+
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+ spin_lock_irq(&tmr->gtm->lock);
+
+ tmr->requested = false;
+
+ spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz, u16 ref,
+ bool ffr)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned long flags;
+ unsigned int prescaler;
+ u8 iclk = GTMDR_ICLK_ICLK;
+ u8 psr;
+ u8 sps;
+
+ prescaler = gtm->clock / hz;
+
+ /*
+ * We have two 8 bit prescalers -- primary and secondary (psr, sps),
+ * plus "slow go" mode (clk / 16). So, total prescale value is
+ * 16 * (psr + 1) * (sps + 1).
+ */
+ if (prescaler > 256 * 256 * 16)
+ return -EINVAL;
+
+ if (prescaler > 256 * 256) {
+ iclk = GTMDR_ICLK_SLGO;
+ prescaler /= 16;
+ }
+
+ if (prescaler > 256) {
+ psr = 256 - 1;
+ sps = prescaler / 256 - 1;
+ } else {
+ psr = prescaler - 1;
+ sps = 1 - 1;
+ }
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ /*
+ * Properly reset timers: stop, reset, set up prescalers, reference
+ * value and clear event register.
+ */
+ clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
+ GTCFR_STP(num) | GTCFR_RST(num));
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ out_be16(tmr->gtpsr, psr);
+ clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
+ GTMDR_ORI | (ffr ? GTMDR_FFR : 0));
+ out_be16(tmr->gtcnr, 0);
+ out_be16(tmr->gtrfr, ref);
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ /* Let it be. */
+ clrbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ spin_unlock_irqrestore(>m->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gtm_reset_ref_timer_16);
+
+void gtm_stop_timer_16(struct gtm_timer *tmr)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned long flags;
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ spin_unlock_irqrestore(>m->lock, flags);
+}
+EXPORT_SYMBOL(gtm_stop_timer_16);
+
+static void __init gtm_set_shortcuts(struct gtm_timer *timers,
+ struct gtm_timers_regs __iomem *regs)
+{
+ /*
+ * Yeah, I don't like this either, but timers' registers a bit messed,
+ * so we have to provide shortcuts to write timer independent code.
+ * Alternative option is to create gt*() accessors, but that will be
+ * even uglier and cryptic.
+ */
+ timers[0].gtcfr = ®s->gtcfr1;
+ timers[0].gtmdr = ®s->gtmdr1;
+ timers[0].gtpsr = ®s->gtpsr1;
+ timers[0].gtcnr = ®s->gtcnr1;
+ timers[0].gtrfr = ®s->gtrfr1;
+ timers[0].gtevr = ®s->gtevr1;
+
+ timers[1].gtcfr = ®s->gtcfr1;
+ timers[1].gtmdr = ®s->gtmdr2;
+ timers[1].gtpsr = ®s->gtpsr2;
+ timers[1].gtcnr = ®s->gtcnr2;
+ timers[1].gtrfr = ®s->gtrfr2;
+ timers[1].gtevr = ®s->gtevr2;
+
+ timers[2].gtcfr = ®s->gtcfr2;
+ timers[2].gtmdr = ®s->gtmdr3;
+ timers[2].gtpsr = ®s->gtpsr3;
+ timers[2].gtcnr = ®s->gtcnr3;
+ timers[2].gtrfr = ®s->gtrfr3;
+ timers[2].gtevr = ®s->gtevr3;
+
+ timers[3].gtcfr = ®s->gtcfr2;
+ timers[3].gtmdr = ®s->gtmdr4;
+ timers[3].gtpsr = ®s->gtpsr4;
+ timers[3].gtcnr = ®s->gtcnr4;
+ timers[3].gtrfr = ®s->gtrfr4;
+ timers[3].gtevr = ®s->gtevr4;
+}
+
+static int __init gtm_get_clock(struct gtm *gtm, struct device_node *np)
+{
+ struct device_node *parent;
+ const u32 *clock;
+ int size;
+ int ret;
+
+ parent = of_get_parent(np);
+ if (!parent) {
+ pr_err("%s: no parent?\n", np->full_name);
+ return -EINVAL;
+ }
+
+ clock = of_get_property(parent, "clock-frequency", &size);
+ if (!clock || size != sizeof(*clock)) {
+ pr_err("%s: no clock-frequency for %s\n",
+ np->full_name, parent->full_name);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = 0;
+ gtm->clock = *clock;
+err:
+ of_node_put(parent);
+ return ret;
+}
+
+static int __init gtm_init_gtm(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,gtm") {
+ int i;
+ struct gtm *gtm;
+
+ gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+ if (!gtm) {
+ pr_err("%s: unable to allocate memory\n",
+ np->full_name);
+ continue;
+ }
+
+ spin_lock_init(>m->lock);
+
+ if (gtm_get_clock(gtm, np))
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ int ret;
+ struct resource irq;
+
+ ret = of_irq_to_resource(np, i, &irq);
+ if (ret == NO_IRQ) {
+ pr_err("%s: not enough interrupts specified\n",
+ np->full_name);
+ goto err;
+ }
+ gtm->timers[i].irq = irq.start;
+ gtm->timers[i].gtm = gtm;
+ }
+
+ gtm->regs = of_iomap(np, 0);
+ if (!gtm->regs) {
+ pr_err("%s: unable to iomap registers\n",
+ np->full_name);
+ goto err;
+ }
+
+ gtm_set_shortcuts(gtm->timers, gtm->regs);
+
+ /* We don't want to lose the node and its ->data */
+ of_node_get(np);
+ np->data = gtm;
+
+ continue;
+err:
+ kfree(gtm);
+ }
+ return 0;
+}
+arch_initcall(gtm_init_gtm);
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index adc6621..c1f2849 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -20,3 +20,8 @@ config UCC
bool
default y if UCC_FAST || UCC_SLOW
+config QE_GTM
+ bool
+ default y if FSL_GTM
+ help
+ QE General-purpose Timers Module support
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 874fe1a..3297a52 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
obj-$(CONFIG_UCC) += ucc.o
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
+obj-$(CONFIG_QE_GTM) += gtm.o
diff --git a/arch/powerpc/sysdev/qe_lib/gtm.c b/arch/powerpc/sysdev/qe_lib/gtm.c
new file mode 100644
index 0000000..2ce9c25
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/gtm.c
@@ -0,0 +1,47 @@
+/*
+ * QE General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/qe.h>
+#include <asm/fsl_gtm.h>
+
+/*
+ * For now we just fixing up the clock -- it's brg-frequency for QE
+ * chips, generic code does not and should not know these details.
+ *
+ * Later we might want to set up BRGs, when QE will actually use
+ * them (there are TIMERCS bits in the CMXGCR register, but today
+ * these bits seem to be no-ops.
+ */
+static int __init qe_init_gtm(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,qe-gtm") {
+ struct gtm *gtm = np->data;
+
+ if (!gtm) {
+ /* fsl,qe-gtm without fsl,gtm compatible? */
+ WARN_ON(1);
+ continue;
+ }
+
+ gtm->clock = qe_get_brg_clk();
+ }
+
+ return 0;
+}
+arch_initcall(qe_init_gtm);
diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm.h
new file mode 100644
index 0000000..bdb9d5a
--- /dev/null
+++ b/include/asm-powerpc/fsl_gtm.h
@@ -0,0 +1,138 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0)
+
+#define GTMDR_ICLK_MASK (3 << 1)
+#define GTMDR_ICLK_ICAS (0 << 1)
+#define GTMDR_ICLK_ICLK (1 << 1)
+#define GTMDR_ICLK_SLGO (2 << 1)
+#define GTMDR_FFR (1 << 3)
+#define GTMDR_ORI (1 << 4)
+#define GTMDR_SPS(x) ((x) << 8)
+
+struct gtm_timers_regs {
+ u8 gtcfr1; /* Timer 1, Timer 2 global config register */
+ u8 res0[0x3];
+ u8 gtcfr2; /* Timer 3, timer 4 global config register */
+ u8 res1[0xB];
+ __be16 gtmdr1; /* Timer 1 mode register */
+ __be16 gtmdr2; /* Timer 2 mode register */
+ __be16 gtrfr1; /* Timer 1 reference register */
+ __be16 gtrfr2; /* Timer 2 reference register */
+ __be16 gtcpr1; /* Timer 1 capture register */
+ __be16 gtcpr2; /* Timer 2 capture register */
+ __be16 gtcnr1; /* Timer 1 counter */
+ __be16 gtcnr2; /* Timer 2 counter */
+ __be16 gtmdr3; /* Timer 3 mode register */
+ __be16 gtmdr4; /* Timer 4 mode register */
+ __be16 gtrfr3; /* Timer 3 reference register */
+ __be16 gtrfr4; /* Timer 4 reference register */
+ __be16 gtcpr3; /* Timer 3 capture register */
+ __be16 gtcpr4; /* Timer 4 capture register */
+ __be16 gtcnr3; /* Timer 3 counter */
+ __be16 gtcnr4; /* Timer 4 counter */
+ __be16 gtevr1; /* Timer 1 event register */
+ __be16 gtevr2; /* Timer 2 event register */
+ __be16 gtevr3; /* Timer 3 event register */
+ __be16 gtevr4; /* Timer 4 event register */
+ __be16 gtpsr1; /* Timer 1 prescale register */
+ __be16 gtpsr2; /* Timer 2 prescale register */
+ __be16 gtpsr3; /* Timer 3 prescale register */
+ __be16 gtpsr4; /* Timer 4 prescale register */
+ u8 res2[0x40];
+} __attribute__ ((packed));
+
+struct gtm_timer {
+ unsigned int irq;
+
+ struct gtm *gtm;
+ bool requested;
+ u8 __iomem *gtcfr;
+ __be16 __iomem *gtmdr;
+ __be16 __iomem *gtpsr;
+ __be16 __iomem *gtcnr;
+ __be16 __iomem *gtrfr;
+ __be16 __iomem *gtevr;
+};
+
+struct gtm {
+ unsigned int clock;
+ struct gtm_timers_regs __iomem *regs;
+ struct gtm_timer timers[4];
+ spinlock_t lock;
+};
+
+/**
+ * gtm_get_timer - request GTM timer for use with the rest of GTM API
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+extern struct gtm_timer *gtm_get_timer(int width);
+
+/**
+ * gtm_put_timer - release GTM timer
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function releases GTM timer sp others might request it.
+ */
+extern void gtm_put_timer(struct gtm_timer *tmr);
+
+/**
+ * gtm_reset_ref_timer_16 - (re)set single (16 bits) timer in reference mode
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @hz: timer rate in Hz
+ * @ref: refernce value
+ * @ffr: free run flag
+ *
+ * Thus function (re)sets GTM timer so it counts up to the reference value and
+ * fires the interrupt when the value is reached. If ffr flag is set, timer
+ * will also reset itself upon reference value, otherwise it continues to
+ * increment.
+ */
+extern int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz,
+ u16 ref, bool ffr);
+
+/**
+ * gtm_ack_ref_timer_16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+static inline void gtm_ack_ref_timer_16(struct gtm_timer *tmr)
+{
+ out_be16(tmr->gtevr, 0xFFFF);
+}
+
+/**
+ * gtm_stop_timer_16 - stop single timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * This function simply stops the GTM timer.
+ */
+extern void gtm_stop_timer_16(struct gtm_timer *tmr);
+
+#endif /* __ASM_FSL_GTM_H */
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (5 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-04-14 20:29 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings Anton Vorontsov
2008-04-14 15:14 ` [PATCH 0/8] A bit of new code and sparse cleanups along the way Kumar Gala
8 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
I believe QE USB clocks routing is qe_lib authority, so usb.c
created. Also, now cmxgcr needs its own lock.
This patch also fixes QE_USB_RESTART_TX command definition.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/Kconfig | 6 ++++
arch/powerpc/sysdev/qe_lib/Makefile | 1 +
arch/powerpc/sysdev/qe_lib/ucc.c | 7 ++--
arch/powerpc/sysdev/qe_lib/usb.c | 57 +++++++++++++++++++++++++++++++++++
include/asm-powerpc/qe.h | 18 ++++++++++-
5 files changed, 85 insertions(+), 4 deletions(-)
create mode 100644 arch/powerpc/sysdev/qe_lib/usb.c
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index c1f2849..f09dae4 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -25,3 +25,9 @@ config QE_GTM
default y if FSL_GTM
help
QE General-purpose Timers Module support
+
+config QE_USB
+ bool
+ default y if USB_FHCI_HCD
+ help
+ QE USB Host Controller support
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 3297a52..c666a59 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_UCC) += ucc.o
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
obj-$(CONFIG_QE_GTM) += gtm.o
+obj-$(CONFIG_QE_USB) += usb.o
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 0e348d9..d3c7f5a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -26,7 +26,8 @@
#include <asm/qe.h>
#include <asm/ucc.h>
-static DEFINE_SPINLOCK(ucc_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
{
@@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
if (ucc_num > UCC_MAX_NUM - 1)
return -EINVAL;
- spin_lock_irqsave(&ucc_lock, flags);
+ spin_lock_irqsave(&cmxgcr_lock, flags);
clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
- spin_unlock_irqrestore(&ucc_lock, flags);
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
return 0;
}
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c
new file mode 100644
index 0000000..60ce676
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/usb.c
@@ -0,0 +1,57 @@
+/*
+ * QE USB routines
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+int qe_usb_clock_set(enum qe_clock clk, int rate)
+{
+ struct qe_mux __iomem *mux = &qe_immr->qmx;
+ unsigned long flags;
+ const bool is_brg = clk < QE_CLK1;
+ u32 val;
+
+ switch (clk) {
+ case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
+ case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
+ case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
+ case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
+ case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
+ case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
+ case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
+ case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
+ case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
+ case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
+ default:
+ pr_err("%s: requested unknown clock %d\n", __func__, clk);
+ return -EINVAL;
+ }
+
+ if (is_brg)
+ qe_setbrg(clk, rate, 1);
+
+ spin_lock_irqsave(&cmxgcr_lock, flags);
+
+ clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
+
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(qe_usb_clock_set);
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index c3be6e2..3276b06 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -16,6 +16,7 @@
#define _ASM_POWERPC_QE_H
#ifdef __KERNEL__
+#include <linux/spinlock.h>
#include <asm/immap_qe.h>
#define QE_NUM_OF_SNUM 28
@@ -74,6 +75,8 @@ enum qe_clock {
QE_CLK_DUMMY
};
+extern spinlock_t cmxgcr_lock;
+
/* Export QE common operations */
extern void qe_reset(void);
extern int par_io_init(struct device_node *np);
@@ -156,6 +159,9 @@ int qe_upload_firmware(const struct qe_firmware *firmware);
/* Obtain information on the uploaded firmware */
struct qe_firmware_info *qe_get_firmware_info(void);
+/* QE USB */
+int qe_usb_clock_set(enum qe_clock clk, int rate);
+
/* Buffer descriptors */
struct qe_bd {
__be16 status;
@@ -254,6 +260,16 @@ enum comm_dir {
#define QE_CMXGCR_MII_ENET_MNG 0x00007000
#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
#define QE_CMXGCR_USBCS 0x0000000f
+#define QE_CMXGCR_USBCS_CLK3 0x1
+#define QE_CMXGCR_USBCS_CLK5 0x2
+#define QE_CMXGCR_USBCS_CLK7 0x3
+#define QE_CMXGCR_USBCS_CLK9 0x4
+#define QE_CMXGCR_USBCS_CLK13 0x5
+#define QE_CMXGCR_USBCS_CLK17 0x6
+#define QE_CMXGCR_USBCS_CLK19 0x7
+#define QE_CMXGCR_USBCS_CLK21 0x8
+#define QE_CMXGCR_USBCS_BRG9 0x9
+#define QE_CMXGCR_USBCS_BRG10 0xa
/* QE CECR Commands.
*/
@@ -283,7 +299,7 @@ enum comm_dir {
#define QE_HPAC_START_TX 0x0000060b
#define QE_HPAC_START_RX 0x0000070b
#define QE_USB_STOP_TX 0x0000000a
-#define QE_USB_RESTART_TX 0x0000000b
+#define QE_USB_RESTART_TX 0x0000000c
#define QE_QMC_STOP_TX 0x0000000c
#define QE_QMC_STOP_RX 0x0000000d
#define QE_SS7_SU_FIL_RESET 0x0000000e
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (6 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB Anton Vorontsov
@ 2008-03-11 17:24 ` Anton Vorontsov
2008-04-14 15:12 ` Kumar Gala
2008-04-14 15:14 ` [PATCH 0/8] A bit of new code and sparse cleanups along the way Kumar Gala
8 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/qe_io.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 736c1fc..93916a4 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <asm/io.h>
+#include <asm/qe.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
@@ -41,7 +42,7 @@ struct port_regs {
#endif
};
-static struct port_regs *par_io = NULL;
+static struct port_regs __iomem *par_io;
static int num_par_io_ports = 0;
int par_io_init(struct device_node *np)
@@ -165,7 +166,7 @@ int par_io_of_config(struct device_node *np)
}
ph = of_get_property(np, "pio-handle", NULL);
- if (ph == 0) {
+ if (ph == NULL) {
printk(KERN_ERR "pio-handle not available \n");
return -1;
}
--
1.5.2.2
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk()
2008-03-11 17:24 ` [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk() Anton Vorontsov
@ 2008-03-11 18:36 ` Kumar Gala
2008-03-11 18:44 ` Anton Vorontsov
2008-04-14 15:11 ` Kumar Gala
1 sibling, 1 reply; 47+ messages in thread
From: Kumar Gala @ 2008-03-11 18:36 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> qe_get_brg_clk() will be used by the fsl_gtm routines.
What is the GTM code going to be used for?
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk()
2008-03-11 18:36 ` Kumar Gala
@ 2008-03-11 18:44 ` Anton Vorontsov
0 siblings, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-11 18:44 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
On Tue, Mar 11, 2008 at 01:36:16PM -0500, Kumar Gala wrote:
>
> On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
>
> >qe_get_brg_clk() will be used by the fsl_gtm routines.
>
> What is the GTM code going to be used for?
Freescale QE USB Host Controller. I posted that driver already,
but will resend the updated one soon.
--
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-11 17:24 ` [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support Anton Vorontsov
@ 2008-03-18 17:43 ` Scott Wood
2008-03-18 19:21 ` Anton Vorontsov
2008-04-08 9:01 ` Laurent Pinchart
1 sibling, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-03-18 17:43 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Tue, Mar 11, 2008 at 08:24:29PM +0300, Anton Vorontsov wrote:
> + Required properties:
> + - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
> + GTMs).
> + - reg : should contain gtm registers location and length (0x40).
> + - interrupts : should contain four interrupts.
> + - interrupt-parent : interrupt source phandle.
interrupt-parent isn't required; it's perfectly valid to specify that in the
parent node instead.
> + Example:
> +
> + gtm@500 {
> + compatible = "fsl,gtm";
> + reg = <0x500 0x40>;
> + interrupts = <90 8 78 8 84 8 72 8>;
> + interrupt-parent = <&ipic>;
> + };
> +
> + gtm@440 {
> + compatible = "fsl,qe-gtm", "fsl,gtm";
> + reg = <0x440 0x40>;
> + interrupts = <12 13 14 15>;
> + interrupt-parent = <&qeic>;
> + };
"timer" would be a better node name than "gtm".
> +static int __init gtm_init_gtm(void)
Name seems rather redundant... what's wrong with gtm_init()?
> +/*
> + * For now we just fixing up the clock -- it's brg-frequency for QE
> + * chips, generic code does not and should not know these details.
> + *
> + * Later we might want to set up BRGs, when QE will actually use
> + * them (there are TIMERCS bits in the CMXGCR register, but today
> + * these bits seem to be no-ops.
> + */
> +static int __init qe_init_gtm(void)
> +{
> + struct device_node *np;
> +
> + for_each_compatible_node(np, NULL, "fsl,qe-gtm") {
> + struct gtm *gtm = np->data;
> +
> + if (!gtm) {
> + /* fsl,qe-gtm without fsl,gtm compatible? */
> + WARN_ON(1);
> + continue;
> + }
> +
> + gtm->clock = qe_get_brg_clk();
> + }
> +
> + return 0;
> +}
> +arch_initcall(qe_init_gtm);
If this happens before the gtm_init_gtm(), then np->data will not be set.
If this happens after gtm_init_gtm(), then gtm_init_gtm() will fail in
gtm_get_clock(), if there's no clock-frequency -- and if there is, then why
do we need qe_init_gtm() at all?
> +/**
> + * gtm_get_timer - request GTM timer for use with the rest of GTM API
> + * @width: timer width (only 16 bits wide timers implemented so far)
> + *
> + * This function reserves GTM timer for later use. It returns gtm_timer
> + * structure to use with the rest of GTM API, you should use timer->irq
> + * to manage timer interrupt.
> + */
> +extern struct gtm_timer *gtm_get_timer(int width);
To support using the GTM as a wakeup from deep sleep on 831x (which I've had
a patch pending for quite a while now), we'll need some way of reserving a
specific timer (only GTM1, timer 4 is supported).
> +/**
> + * gtm_put_timer - release GTM timer
> + * @width: timer width (only 16 bits wide timers implemented so far)
> + *
> + * This function releases GTM timer sp others might request it.
> + */
> +extern void gtm_put_timer(struct gtm_timer *tmr);
> +
> +/**
> + * gtm_reset_ref_timer_16 - (re)set single (16 bits) timer in reference mode
> + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> + * @hz: timer rate in Hz
> + * @ref: refernce value
How about "period" or "expiry"? And it'd be better to let the caller
request a time in some real unit (e.g. microseconds), and let the gtm driver
figure out how to divide that between prescaler and reference value,
especially in the absence of a way to ask for the allowable hz ranges.
> + * @ffr: free run flag
Could we call it something more intuitive such as "freerun"?
> + * Thus function (re)sets GTM timer so it counts up to the reference value and
> + * fires the interrupt when the value is reached. If ffr flag is set, timer
> + * will also reset itself upon reference value, otherwise it continues to
> + * increment.
> + */
> +extern int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz,
> + u16 ref, bool ffr);
> +
> +/**
> + * gtm_ack_ref_timer_16 - acknowledge timer event (free-run timers only)
> + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> + *
> + * Thus function used to acknowledge timer interrupt event, use it inside the
> + * interrupt handler.
> + */
> +static inline void gtm_ack_ref_timer_16(struct gtm_timer *tmr)
What does the "ref" mean in these names?
How about "gtm_arm_timer16" and "gtm_ack_timer16"?
> +{
> + out_be16(tmr->gtevr, 0xFFFF);
> +}
You need to include <asm/io.h> for this.
Don't blindly clear all events, just the events that have been acted upon.
Either take the events as an argument, or make the ack function specific to
REF, and only set that bit.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset
2008-03-11 17:24 ` [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset Anton Vorontsov
@ 2008-03-18 17:48 ` Scott Wood
2008-04-14 15:11 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Scott Wood @ 2008-03-18 17:48 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Tue, Mar 11, 2008 at 08:24:13PM +0300, Anton Vorontsov wrote:
> qe_muram_offset is the reverse of the qe_muram_addr, will be
> used for the Freescale QE USB Host Controller driver.
>
> This patch also moves qe_muram_addr into the qe.h header, plus
> adds __iomem hints to use with sparse.
We should really switch QE over to using the muram code in cpm_common.c...
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-18 17:43 ` Scott Wood
@ 2008-03-18 19:21 ` Anton Vorontsov
2008-03-18 19:55 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-18 19:21 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Tue, Mar 18, 2008 at 12:43:29PM -0500, Scott Wood wrote:
> On Tue, Mar 11, 2008 at 08:24:29PM +0300, Anton Vorontsov wrote:
> > + Required properties:
> > + - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
> > + GTMs).
> > + - reg : should contain gtm registers location and length (0x40).
> > + - interrupts : should contain four interrupts.
> > + - interrupt-parent : interrupt source phandle.
>
> interrupt-parent isn't required; it's perfectly valid to specify that in the
> parent node instead.
Ok
>
> > + Example:
> > +
> > + gtm@500 {
> > + compatible = "fsl,gtm";
> > + reg = <0x500 0x40>;
> > + interrupts = <90 8 78 8 84 8 72 8>;
> > + interrupt-parent = <&ipic>;
> > + };
> > +
> > + gtm@440 {
> > + compatible = "fsl,qe-gtm", "fsl,gtm";
> > + reg = <0x440 0x40>;
> > + interrupts = <12 13 14 15>;
> > + interrupt-parent = <&qeic>;
> > + };
>
> "timer" would be a better node name than "gtm".
Ok
> > +static int __init gtm_init_gtm(void)
>
> Name seems rather redundant... what's wrong with gtm_init()?
Probably :%s/// effect. Will fix.
> > +/*
> > + * For now we just fixing up the clock -- it's brg-frequency for QE
> > + * chips, generic code does not and should not know these details.
> > + *
> > + * Later we might want to set up BRGs, when QE will actually use
> > + * them (there are TIMERCS bits in the CMXGCR register, but today
> > + * these bits seem to be no-ops.
> > + */
> > +static int __init qe_init_gtm(void)
> > +{
> > + struct device_node *np;
> > +
> > + for_each_compatible_node(np, NULL, "fsl,qe-gtm") {
> > + struct gtm *gtm = np->data;
> > +
> > + if (!gtm) {
> > + /* fsl,qe-gtm without fsl,gtm compatible? */
> > + WARN_ON(1);
> > + continue;
> > + }
> > +
> > + gtm->clock = qe_get_brg_clk();
> > + }
> > +
> > + return 0;
> > +}
> > +arch_initcall(qe_init_gtm);
>
> If this happens before the gtm_init_gtm(),
"If" isn't possible, order is guaranteed.
> then np->data will not be set.
It's a bug in the device tree or in the Linux code then.
> If this happens after gtm_init_gtm(), then gtm_init_gtm() will fail in
> gtm_get_clock(), if there's no clock-frequency -- and if there is, then why
> do we need qe_init_gtm() at all?
Because for the QE clock-frequency != brg-frequency.
> > +/**
> > + * gtm_get_timer - request GTM timer for use with the rest of GTM API
> > + * @width: timer width (only 16 bits wide timers implemented so far)
> > + *
> > + * This function reserves GTM timer for later use. It returns gtm_timer
> > + * structure to use with the rest of GTM API, you should use timer->irq
> > + * to manage timer interrupt.
> > + */
> > +extern struct gtm_timer *gtm_get_timer(int width);
>
> To support using the GTM as a wakeup from deep sleep on 831x (which I've had
> a patch pending for quite a while now), we'll need some way of reserving a
> specific timer (only GTM1, timer 4 is supported).
You can add reserve function either in the PM driver (if any), or
you can do something in the device tree (wakeup-timer = <..>). I don't
see any problems if you want to implement it.
> > +/**
> > + * gtm_put_timer - release GTM timer
> > + * @width: timer width (only 16 bits wide timers implemented so far)
> > + *
> > + * This function releases GTM timer sp others might request it.
> > + */
> > +extern void gtm_put_timer(struct gtm_timer *tmr);
> > +
> > +/**
> > + * gtm_reset_ref_timer_16 - (re)set single (16 bits) timer in reference mode
> > + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> > + * @hz: timer rate in Hz
> > + * @ref: refernce value
>
> How about "period" or "expiry"? And it'd be better to let the caller
> request a time in some real unit (e.g. microseconds), and let the gtm driver
> figure out how to divide that between prescaler and reference value,
> especially in the absence of a way to ask for the allowable hz ranges.
Will think about it.
> > + * @ffr: free run flag
>
> Could we call it something more intuitive such as "freerun"?
Easy.
> > + * Thus function (re)sets GTM timer so it counts up to the reference value and
> > + * fires the interrupt when the value is reached. If ffr flag is set, timer
> > + * will also reset itself upon reference value, otherwise it continues to
> > + * increment.
> > + */
> > +extern int gtm_reset_ref_timer_16(struct gtm_timer *tmr, unsigned int hz,
> > + u16 ref, bool ffr);
> > +
> > +/**
> > + * gtm_ack_ref_timer_16 - acknowledge timer event (free-run timers only)
> > + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> > + *
> > + * Thus function used to acknowledge timer interrupt event, use it inside the
> > + * interrupt handler.
> > + */
> > +static inline void gtm_ack_ref_timer_16(struct gtm_timer *tmr)
>
> What does the "ref" mean in these names?
>
> How about "gtm_arm_timer16" and "gtm_ack_timer16"?
Ok.
>
> > +{
> > + out_be16(tmr->gtevr, 0xFFFF);
> > +}
>
> You need to include <asm/io.h> for this.
Ok.
> Don't blindly clear all events, just the events that have been acted upon.
> Either take the events as an argument, or make the ack function specifi
Ok.
Thanks,
--
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-18 19:21 ` Anton Vorontsov
@ 2008-03-18 19:55 ` Scott Wood
2008-03-18 20:27 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-03-18 19:55 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
Anton Vorontsov wrote:
>>> +arch_initcall(qe_init_gtm);
>> If this happens before the gtm_init_gtm(),
>
> "If" isn't possible, order is guaranteed.
You use arch_initcall for both, so you're relying on link order. I
think this at least merits a comment.
>> then np->data will not be set.
>
> It's a bug in the device tree or in the Linux code then.
Hmm? It's set by gtm_init_gtm(). If this code runs before
gtm_init_gtm(), what are you expecting to initialize np->data?
>> If this happens after gtm_init_gtm(), then gtm_init_gtm() will fail in
>> gtm_get_clock(), if there's no clock-frequency -- and if there is, then why
>> do we need qe_init_gtm() at all?
>
> Because for the QE clock-frequency != brg-frequency.
Sorry, I missed that you were getting clock-frequency from the parent,
rather than the gtm node. If you do the latter, then you can just stick
the relevant frequency in the gtm node and not worry about where it
comes from. This would be analogous to how UART clocks are specified.
Also, what if some arch_initcall runs between gtm_init_gtm and
qe_init_gtm, that registers itself as a client of the gtm driver, and
uses the wrong clock value?
>>> +extern struct gtm_timer *gtm_get_timer(int width);
>> To support using the GTM as a wakeup from deep sleep on 831x (which I've had
>> a patch pending for quite a while now), we'll need some way of reserving a
>> specific timer (only GTM1, timer 4 is supported).
>
> You can add reserve function either in the PM driver (if any), or
What I meant was that there needs to be some way of telling this driver
not to hand the reserved timer out to some other client.
> you can do something in the device tree (wakeup-timer = <..>). I don't
> see any problems if you want to implement it.
How about simply having optional arguments to gtm_get_timer() to specify
the GTM device and timer number, which will fail if it's already in use?
Then, the PM driver simply needs to run early enough to grab the timer
it needs.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-18 19:55 ` Scott Wood
@ 2008-03-18 20:27 ` Anton Vorontsov
2008-03-18 20:48 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-03-18 20:27 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Tue, Mar 18, 2008 at 02:55:14PM -0500, Scott Wood wrote:
> Anton Vorontsov wrote:
> >>>+arch_initcall(qe_init_gtm);
> >>If this happens before the gtm_init_gtm(),
> >
> >"If" isn't possible, order is guaranteed.
>
> You use arch_initcall for both, so you're relying on link order. I
> think this at least merits a comment.
> >>then np->data will not be set.
> >
> >It's a bug in the device tree or in the Linux code then.
>
> Hmm? It's set by gtm_init_gtm(). If this code runs before
> gtm_init_gtm(), what are you expecting to initialize np->data?
What code exactly?
> >>If this happens after gtm_init_gtm(), then gtm_init_gtm() will fail in
> >>gtm_get_clock(), if there's no clock-frequency -- and if there is, then
> >>why
> >>do we need qe_init_gtm() at all?
> >
> >Because for the QE clock-frequency != brg-frequency.
>
> Sorry, I missed that you were getting clock-frequency from the parent,
> rather than the gtm node. If you do the latter, then you can just stick
> the relevant frequency in the gtm node and not worry about where it
> comes from. This would be analogous to how UART clocks are specified.
Ok.
> Also, what if some arch_initcall runs between gtm_init_gtm and
> qe_init_gtm, that registers itself as a client of the gtm driver, and
> uses the wrong clock value?
Again, what code exactly? If it is a driver (for what this API is
created for), it hardly will run earlier than arch/ code. If this is
platform code (arch/powerpc/platform/), then it is hardly will run
earlier than arch/sysdev/. Inside the arch/sysdev/ fsl_gtm.c is
guaranteed to run earlier than qe_lib/gtm.c. So, where is the problem?
Since I'll implement clock-frequency inside the timer node, this
isn't relevant anymore...
> >>>+extern struct gtm_timer *gtm_get_timer(int width);
> >>To support using the GTM as a wakeup from deep sleep on 831x (which I've
> >>had
> >>a patch pending for quite a while now), we'll need some way of reserving a
> >>specific timer (only GTM1, timer 4 is supported).
> >
> >You can add reserve function either in the PM driver (if any), or
>
> What I meant was that there needs to be some way of telling this driver
> not to hand the reserved timer out to some other client.
>
> >you can do something in the device tree (wakeup-timer = <..>). I don't
> >see any problems if you want to implement it.
>
> How about simply having optional arguments to gtm_get_timer() to specify
> the GTM device and timer number, which will fail if it's already in use?
> Then, the PM driver simply needs to run early enough to grab the timer
> it needs.
Ah. You need specific timer. No problem. I don't like idea of new arguments
to the gtm_get_timer() function (complicates things), but we can just
implement another one. gtm_get_timer_<name>, choice the name please.
_specific, _2, _for, __gtm_get_timer, ...
--
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-18 20:27 ` Anton Vorontsov
@ 2008-03-18 20:48 ` Scott Wood
2008-04-16 18:39 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-03-18 20:48 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
Anton Vorontsov wrote:
> On Tue, Mar 18, 2008 at 02:55:14PM -0500, Scott Wood wrote:
>> Anton Vorontsov wrote:
>>>>> +arch_initcall(qe_init_gtm);
>>>> If this happens before the gtm_init_gtm(),
>>> "If" isn't possible, order is guaranteed.
>> You use arch_initcall for both, so you're relying on link order. I
>> think this at least merits a comment.
>>>> then np->data will not be set.
>>> It's a bug in the device tree or in the Linux code then.
>> Hmm? It's set by gtm_init_gtm(). If this code runs before
>> gtm_init_gtm(), what are you expecting to initialize np->data?
>
> What code exactly?
Sorry, "this code" == qe_init_gtm(). Obviously, if you assume that
gtm_init_gtm() will always be linked earlier, then it's not an issue.
>> Also, what if some arch_initcall runs between gtm_init_gtm and
>> qe_init_gtm, that registers itself as a client of the gtm driver, and
>> uses the wrong clock value?
>
> Again, what code exactly? If it is a driver (for what this API is
> created for), it hardly will run earlier than arch/ code. If this is
> platform code (arch/powerpc/platform/), then it is hardly will run
> earlier than arch/sysdev/. Inside the arch/sysdev/ fsl_gtm.c is
> guaranteed to run earlier than qe_lib/gtm.c. So, where is the problem?
That's a lot of implicit, undocumented dependency on link order...
Things can be moved around, and driver-ish code can pop up in surprising
places. All I meant was that having the gtm driver present itself as
ready when it isn't, in a way which isn't readily apparent if it
happens, is worrysome.
> Since I'll implement clock-frequency inside the timer node, this
> isn't relevant anymore...
OK, good.
> Ah. You need specific timer. No problem. I don't like idea of new arguments
> to the gtm_get_timer() function (complicates things), but we can just
> implement another one. gtm_get_timer_<name>, choice the name please.
> _specific, _2, _for, __gtm_get_timer, ...
How about:
struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
int width);
...with np->data used by the caller to figure out which gtm pointer to
pass in.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-11 17:24 ` [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support Anton Vorontsov
2008-03-18 17:43 ` Scott Wood
@ 2008-04-08 9:01 ` Laurent Pinchart
2008-04-08 11:48 ` Anton Vorontsov
1 sibling, 1 reply; 47+ messages in thread
From: Laurent Pinchart @ 2008-04-08 9:01 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1527 bytes --]
On Tuesday 11 March 2008 18:24, Anton Vorontsov wrote:
> GTM stands for General-purpose Timers Module and able to generate
> timer{1,2,3,4} interrupts.
>
> There are several limitations in this support:
> 1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
> This is straightforward to implement when needed, two timers should
> be marked as "requested" and configured as appropriate.
> 2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
> This is also straightforward to implement when needed, all timers
> should be marked as "requested" and configured as appropriate.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
[snip]
> +void gtm_stop_timer_16(struct gtm_timer *tmr)
> +{
> + struct gtm *gtm = tmr->gtm;
> + int num = tmr - >m->timers[0];
> + unsigned long flags;
> +
> + spin_lock_irqsave(>m->lock, flags);
> +
> + setbits8(tmr->gtcfr, GTCFR_STP(num));
Shouldn't we clear the timer events with
out_be16(tmr->gtevr, 0xFFFF);
here ? Otherwise the timer interrupt could still fire after the timer is
stopped. This introduces a race condition in drivers that blindly re-arm the
timer in the interrupt handler. I've been bitten by this while porting your
FHCI USB driver to a CPM2 platform.
> +
> + spin_unlock_irqrestore(>m->lock, flags);
> +}
> +EXPORT_SYMBOL(gtm_stop_timer_16);
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-08 9:01 ` Laurent Pinchart
@ 2008-04-08 11:48 ` Anton Vorontsov
0 siblings, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-08 11:48 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linuxppc-dev
On Tue, Apr 08, 2008 at 11:01:53AM +0200, Laurent Pinchart wrote:
> On Tuesday 11 March 2008 18:24, Anton Vorontsov wrote:
> > GTM stands for General-purpose Timers Module and able to generate
> > timer{1,2,3,4} interrupts.
> >
> > There are several limitations in this support:
> > 1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
> > This is straightforward to implement when needed, two timers should
> > be marked as "requested" and configured as appropriate.
> > 2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
> > This is also straightforward to implement when needed, all timers
> > should be marked as "requested" and configured as appropriate.
> >
> > Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
>
> [snip]
>
> > +void gtm_stop_timer_16(struct gtm_timer *tmr)
> > +{
> > + struct gtm *gtm = tmr->gtm;
> > + int num = tmr - >m->timers[0];
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(>m->lock, flags);
> > +
> > + setbits8(tmr->gtcfr, GTCFR_STP(num));
>
> Shouldn't we clear the timer events with
>
> out_be16(tmr->gtevr, 0xFFFF);
Yeah.
> here ? Otherwise the timer interrupt could still fire after the timer is
> stopped. This introduces a race condition in drivers that blindly re-arm the
> timer in the interrupt handler. I've been bitten by this while porting your
> FHCI USB driver to a CPM2 platform.
Thanks, will fix.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
@ 2008-04-11 14:06 ` Kumar Gala
2008-04-13 12:53 ` David Woodhouse
2008-04-14 15:10 ` Kumar Gala
1 sibling, 1 reply; 47+ messages in thread
From: Kumar Gala @ 2008-04-11 14:06 UTC (permalink / raw)
To: David Woodhouse; +Cc: Scott Wood, linuxppc-dev@ozlabs.org list, linux-mtd
On Mar 11, 2008, at 12:23 PM, Anton Vorontsov wrote:
> This is needed to support other localbus peripherals, such as
> NAND on FSL UPM.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
>
> Would be great if someone from the MTD community will ack this patch
> to go through powerpc trees.
>
> Thanks,
David, can you ack this. It looks good to me but want a MTD
maintainer ack before having it go through the powerpc tree.
- k
>
>
> drivers/mtd/nand/fsl_elbc_nand.c | 219 +
> +-----------------------------------
> include/asm-powerpc/fsl_lbc.h | 223 +++++++++++++++++++++++++++++
> +++++++++
> 2 files changed, 235 insertions(+), 207 deletions(-)
> create mode 100644 include/asm-powerpc/fsl_lbc.h
>
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/
> fsl_elbc_nand.c
> index b025dfe..378b7aa 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -36,207 +36,12 @@
> #include <linux/mtd/partitions.h>
>
> #include <asm/io.h>
> -
> +#include <asm/fsl_lbc.h>
>
> #define MAX_BANKS 8
> #define ERR_BYTE 0xFF /* Value returned for read bytes when read
> failed */
> #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for
> FCM */
>
> -struct elbc_bank {
> - __be32 br; /**< Base Register */
> -#define BR_BA 0xFFFF8000
> -#define BR_BA_SHIFT 15
> -#define BR_PS 0x00001800
> -#define BR_PS_SHIFT 11
> -#define BR_PS_8 0x00000800 /* Port Size 8 bit */
> -#define BR_PS_16 0x00001000 /* Port Size 16 bit */
> -#define BR_PS_32 0x00001800 /* Port Size 32 bit */
> -#define BR_DECC 0x00000600
> -#define BR_DECC_SHIFT 9
> -#define BR_DECC_OFF 0x00000000 /* HW ECC checking and
> generation off */
> -#define BR_DECC_CHK 0x00000200 /* HW ECC checking on,
> generation off */
> -#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and
> generation on */
> -#define BR_WP 0x00000100
> -#define BR_WP_SHIFT 8
> -#define BR_MSEL 0x000000E0
> -#define BR_MSEL_SHIFT 5
> -#define BR_MS_GPCM 0x00000000 /* GPCM */
> -#define BR_MS_FCM 0x00000020 /* FCM */
> -#define BR_MS_SDRAM 0x00000060 /* SDRAM */
> -#define BR_MS_UPMA 0x00000080 /* UPMA */
> -#define BR_MS_UPMB 0x000000A0 /* UPMB */
> -#define BR_MS_UPMC 0x000000C0 /* UPMC */
> -#define BR_V 0x00000001
> -#define BR_V_SHIFT 0
> -#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
> -
> - __be32 or; /**< Base Register */
> -#define OR0 0x5004
> -#define OR1 0x500C
> -#define OR2 0x5014
> -#define OR3 0x501C
> -#define OR4 0x5024
> -#define OR5 0x502C
> -#define OR6 0x5034
> -#define OR7 0x503C
> -
> -#define OR_FCM_AM 0xFFFF8000
> -#define OR_FCM_AM_SHIFT 15
> -#define OR_FCM_BCTLD 0x00001000
> -#define OR_FCM_BCTLD_SHIFT 12
> -#define OR_FCM_PGS 0x00000400
> -#define OR_FCM_PGS_SHIFT 10
> -#define OR_FCM_CSCT 0x00000200
> -#define OR_FCM_CSCT_SHIFT 9
> -#define OR_FCM_CST 0x00000100
> -#define OR_FCM_CST_SHIFT 8
> -#define OR_FCM_CHT 0x00000080
> -#define OR_FCM_CHT_SHIFT 7
> -#define OR_FCM_SCY 0x00000070
> -#define OR_FCM_SCY_SHIFT 4
> -#define OR_FCM_SCY_1 0x00000010
> -#define OR_FCM_SCY_2 0x00000020
> -#define OR_FCM_SCY_3 0x00000030
> -#define OR_FCM_SCY_4 0x00000040
> -#define OR_FCM_SCY_5 0x00000050
> -#define OR_FCM_SCY_6 0x00000060
> -#define OR_FCM_SCY_7 0x00000070
> -#define OR_FCM_RST 0x00000008
> -#define OR_FCM_RST_SHIFT 3
> -#define OR_FCM_TRLX 0x00000004
> -#define OR_FCM_TRLX_SHIFT 2
> -#define OR_FCM_EHTR 0x00000002
> -#define OR_FCM_EHTR_SHIFT 1
> -};
> -
> -struct elbc_regs {
> - struct elbc_bank bank[8];
> - u8 res0[0x28];
> - __be32 mar; /**< UPM Address Register */
> - u8 res1[0x4];
> - __be32 mamr; /**< UPMA Mode Register */
> - __be32 mbmr; /**< UPMB Mode Register */
> - __be32 mcmr; /**< UPMC Mode Register */
> - u8 res2[0x8];
> - __be32 mrtpr; /**< Memory Refresh Timer Prescaler
> Register */
> - __be32 mdr; /**< UPM Data Register */
> - u8 res3[0x4];
> - __be32 lsor; /**< Special Operation Initiation Register
> */
> - __be32 lsdmr; /**< SDRAM Mode Register */
> - u8 res4[0x8];
> - __be32 lurt; /**< UPM Refresh Timer */
> - __be32 lsrt; /**< SDRAM Refresh Timer */
> - u8 res5[0x8];
> - __be32 ltesr; /**< Transfer Error Status Register */
> -#define LTESR_BM 0x80000000
> -#define LTESR_FCT 0x40000000
> -#define LTESR_PAR 0x20000000
> -#define LTESR_WP 0x04000000
> -#define LTESR_ATMW 0x00800000
> -#define LTESR_ATMR 0x00400000
> -#define LTESR_CS 0x00080000
> -#define LTESR_CC 0x00000001
> -#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> - __be32 ltedr; /**< Transfer Error Disable Register */
> - __be32 lteir; /**< Transfer Error Interrupt Register */
> - __be32 lteatr; /**< Transfer Error Attributes Register */
> - __be32 ltear; /**< Transfer Error Address Register */
> - u8 res6[0xC];
> - __be32 lbcr; /**< Configuration Register */
> -#define LBCR_LDIS 0x80000000
> -#define LBCR_LDIS_SHIFT 31
> -#define LBCR_BCTLC 0x00C00000
> -#define LBCR_BCTLC_SHIFT 22
> -#define LBCR_AHD 0x00200000
> -#define LBCR_LPBSE 0x00020000
> -#define LBCR_LPBSE_SHIFT 17
> -#define LBCR_EPAR 0x00010000
> -#define LBCR_EPAR_SHIFT 16
> -#define LBCR_BMT 0x0000FF00
> -#define LBCR_BMT_SHIFT 8
> -#define LBCR_INIT 0x00040000
> - __be32 lcrr; /**< Clock Ratio Register */
> -#define LCRR_DBYP 0x80000000
> -#define LCRR_DBYP_SHIFT 31
> -#define LCRR_BUFCMDC 0x30000000
> -#define LCRR_BUFCMDC_SHIFT 28
> -#define LCRR_ECL 0x03000000
> -#define LCRR_ECL_SHIFT 24
> -#define LCRR_EADC 0x00030000
> -#define LCRR_EADC_SHIFT 16
> -#define LCRR_CLKDIV 0x0000000F
> -#define LCRR_CLKDIV_SHIFT 0
> - u8 res7[0x8];
> - __be32 fmr; /**< Flash Mode Register */
> -#define FMR_CWTO 0x0000F000
> -#define FMR_CWTO_SHIFT 12
> -#define FMR_BOOT 0x00000800
> -#define FMR_ECCM 0x00000100
> -#define FMR_AL 0x00000030
> -#define FMR_AL_SHIFT 4
> -#define FMR_OP 0x00000003
> -#define FMR_OP_SHIFT 0
> - __be32 fir; /**< Flash Instruction Register */
> -#define FIR_OP0 0xF0000000
> -#define FIR_OP0_SHIFT 28
> -#define FIR_OP1 0x0F000000
> -#define FIR_OP1_SHIFT 24
> -#define FIR_OP2 0x00F00000
> -#define FIR_OP2_SHIFT 20
> -#define FIR_OP3 0x000F0000
> -#define FIR_OP3_SHIFT 16
> -#define FIR_OP4 0x0000F000
> -#define FIR_OP4_SHIFT 12
> -#define FIR_OP5 0x00000F00
> -#define FIR_OP5_SHIFT 8
> -#define FIR_OP6 0x000000F0
> -#define FIR_OP6_SHIFT 4
> -#define FIR_OP7 0x0000000F
> -#define FIR_OP7_SHIFT 0
> -#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
> -#define FIR_OP_CA 0x1 /* Issue current column address */
> -#define FIR_OP_PA 0x2 /* Issue current block+page address
> */
> -#define FIR_OP_UA 0x3 /* Issue user defined address */
> -#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
> -#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
> -#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
> -#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
> -#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer
> */
> -#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
> -#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
> -#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
> -#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
> -#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
> -#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
> -#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
> - __be32 fcr; /**< Flash Command Register */
> -#define FCR_CMD0 0xFF000000
> -#define FCR_CMD0_SHIFT 24
> -#define FCR_CMD1 0x00FF0000
> -#define FCR_CMD1_SHIFT 16
> -#define FCR_CMD2 0x0000FF00
> -#define FCR_CMD2_SHIFT 8
> -#define FCR_CMD3 0x000000FF
> -#define FCR_CMD3_SHIFT 0
> - __be32 fbar; /**< Flash Block Address Register */
> -#define FBAR_BLK 0x00FFFFFF
> - __be32 fpar; /**< Flash Page Address Register */
> -#define FPAR_SP_PI 0x00007C00
> -#define FPAR_SP_PI_SHIFT 10
> -#define FPAR_SP_MS 0x00000200
> -#define FPAR_SP_CI 0x000001FF
> -#define FPAR_SP_CI_SHIFT 0
> -#define FPAR_LP_PI 0x0003F000
> -#define FPAR_LP_PI_SHIFT 12
> -#define FPAR_LP_MS 0x00000800
> -#define FPAR_LP_CI 0x000007FF
> -#define FPAR_LP_CI_SHIFT 0
> - __be32 fbcr; /**< Flash Byte Count Register */
> -#define FBCR_BC 0x00000FFF
> - u8 res11[0x8];
> - u8 res8[0xF00];
> -};
> -
> struct fsl_elbc_ctrl;
>
> /* mtd information per set */
> @@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
>
> /* device info */
> struct device *dev;
> - struct elbc_regs __iomem *regs;
> + struct fsl_lbc_regs __iomem *regs;
> int irq;
> wait_queue_head_t irq_wait;
> unsigned int irq_status; /* status read from LTESR by irq handler */
> @@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int
> column, int page_addr, int oob)
> struct nand_chip *chip = mtd->priv;
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> int buf_num;
>
> ctrl->page = page_addr;
> @@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info
> *mtd)
> struct nand_chip *chip = mtd->priv;
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>
> /* Setup the FMR[OP] to execute without write protection */
> out_be32(&lbc->fmr, priv->fmr | 3);
> @@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip
> *chip, int oob)
> {
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>
> if (priv->page_size) {
> out_be32(&lbc->fir,
> @@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info
> *mtd, unsigned int command,
> struct nand_chip *chip = mtd->priv;
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>
> ctrl->use_mdr = 0;
>
> @@ -775,7 +580,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd,
> struct nand_chip *chip)
> {
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>
> if (ctrl->status != LTESR_CC)
> return NAND_STATUS_FAIL;
> @@ -807,7 +612,7 @@ static int fsl_elbc_chip_init_tail(struct
> mtd_info *mtd)
> struct nand_chip *chip = mtd->priv;
> struct fsl_elbc_mtd *priv = chip->priv;
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> unsigned int al;
>
> /* calculate FMR Address Length field */
> @@ -922,7 +727,7 @@ static void fsl_elbc_write_page(struct mtd_info
> *mtd,
> static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
> {
> struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> struct nand_chip *chip = &priv->chip;
>
> dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
> @@ -986,7 +791,7 @@ static int fsl_elbc_chip_remove(struct
> fsl_elbc_mtd *priv)
> static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
> struct device_node *node)
> {
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> struct fsl_elbc_mtd *priv;
> struct resource res;
> #ifdef CONFIG_MTD_PARTITIONS
> @@ -1083,7 +888,7 @@ err:
>
> static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
> {
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>
> /* clear event registers */
> setbits32(&lbc->ltesr, LTESR_NAND_MASK);
> @@ -1128,7 +933,7 @@ static int __devexit
> fsl_elbc_ctrl_remove(struct of_device *ofdev)
> static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
> {
> struct fsl_elbc_ctrl *ctrl = data;
> - struct elbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
>
> if (status) {
> diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/
> fsl_lbc.h
> new file mode 100644
> index 0000000..13a3c28
> --- /dev/null
> +++ b/include/asm-powerpc/fsl_lbc.h
> @@ -0,0 +1,223 @@
> +/* Freescale Local Bus Controller
> + *
> + * Copyright (c) 2006-2007 Freescale Semiconductor
> + *
> + * Authors: Nick Spence <nick.spence@freescale.com>,
> + * Scott Wood <scottwood@freescale.com>
> + *
> + * 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 __ASM_FSL_LBC_H
> +#define __ASM_FSL_LBC_H
> +
> +#include <linux/types.h>
> +
> +struct fsl_lbc_bank {
> + __be32 br; /**< Base Register */
> +#define BR_BA 0xFFFF8000
> +#define BR_BA_SHIFT 15
> +#define BR_PS 0x00001800
> +#define BR_PS_SHIFT 11
> +#define BR_PS_8 0x00000800 /* Port Size 8 bit */
> +#define BR_PS_16 0x00001000 /* Port Size 16 bit */
> +#define BR_PS_32 0x00001800 /* Port Size 32 bit */
> +#define BR_DECC 0x00000600
> +#define BR_DECC_SHIFT 9
> +#define BR_DECC_OFF 0x00000000 /* HW ECC checking and
> generation off */
> +#define BR_DECC_CHK 0x00000200 /* HW ECC checking on,
> generation off */
> +#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and
> generation on */
> +#define BR_WP 0x00000100
> +#define BR_WP_SHIFT 8
> +#define BR_MSEL 0x000000E0
> +#define BR_MSEL_SHIFT 5
> +#define BR_MS_GPCM 0x00000000 /* GPCM */
> +#define BR_MS_FCM 0x00000020 /* FCM */
> +#define BR_MS_SDRAM 0x00000060 /* SDRAM */
> +#define BR_MS_UPMA 0x00000080 /* UPMA */
> +#define BR_MS_UPMB 0x000000A0 /* UPMB */
> +#define BR_MS_UPMC 0x000000C0 /* UPMC */
> +#define BR_V 0x00000001
> +#define BR_V_SHIFT 0
> +#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
> +
> + __be32 or; /**< Base Register */
> +#define OR0 0x5004
> +#define OR1 0x500C
> +#define OR2 0x5014
> +#define OR3 0x501C
> +#define OR4 0x5024
> +#define OR5 0x502C
> +#define OR6 0x5034
> +#define OR7 0x503C
> +
> +#define OR_FCM_AM 0xFFFF8000
> +#define OR_FCM_AM_SHIFT 15
> +#define OR_FCM_BCTLD 0x00001000
> +#define OR_FCM_BCTLD_SHIFT 12
> +#define OR_FCM_PGS 0x00000400
> +#define OR_FCM_PGS_SHIFT 10
> +#define OR_FCM_CSCT 0x00000200
> +#define OR_FCM_CSCT_SHIFT 9
> +#define OR_FCM_CST 0x00000100
> +#define OR_FCM_CST_SHIFT 8
> +#define OR_FCM_CHT 0x00000080
> +#define OR_FCM_CHT_SHIFT 7
> +#define OR_FCM_SCY 0x00000070
> +#define OR_FCM_SCY_SHIFT 4
> +#define OR_FCM_SCY_1 0x00000010
> +#define OR_FCM_SCY_2 0x00000020
> +#define OR_FCM_SCY_3 0x00000030
> +#define OR_FCM_SCY_4 0x00000040
> +#define OR_FCM_SCY_5 0x00000050
> +#define OR_FCM_SCY_6 0x00000060
> +#define OR_FCM_SCY_7 0x00000070
> +#define OR_FCM_RST 0x00000008
> +#define OR_FCM_RST_SHIFT 3
> +#define OR_FCM_TRLX 0x00000004
> +#define OR_FCM_TRLX_SHIFT 2
> +#define OR_FCM_EHTR 0x00000002
> +#define OR_FCM_EHTR_SHIFT 1
> +};
> +
> +struct fsl_lbc_regs {
> + struct fsl_lbc_bank bank[8];
> + u8 res0[0x28];
> + __be32 mar; /**< UPM Address Register */
> + u8 res1[0x4];
> + __be32 mamr; /**< UPMA Mode Register */
> + __be32 mbmr; /**< UPMB Mode Register */
> + __be32 mcmr; /**< UPMC Mode Register */
> + u8 res2[0x8];
> + __be32 mrtpr; /**< Memory Refresh Timer Prescaler
> Register */
> + __be32 mdr; /**< UPM Data Register */
> + u8 res3[0x4];
> + __be32 lsor; /**< Special Operation Initiation Register
> */
> + __be32 lsdmr; /**< SDRAM Mode Register */
> + u8 res4[0x8];
> + __be32 lurt; /**< UPM Refresh Timer */
> + __be32 lsrt; /**< SDRAM Refresh Timer */
> + u8 res5[0x8];
> + __be32 ltesr; /**< Transfer Error Status Register */
> +#define LTESR_BM 0x80000000
> +#define LTESR_FCT 0x40000000
> +#define LTESR_PAR 0x20000000
> +#define LTESR_WP 0x04000000
> +#define LTESR_ATMW 0x00800000
> +#define LTESR_ATMR 0x00400000
> +#define LTESR_CS 0x00080000
> +#define LTESR_CC 0x00000001
> +#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> + __be32 ltedr; /**< Transfer Error Disable Register */
> + __be32 lteir; /**< Transfer Error Interrupt Register */
> + __be32 lteatr; /**< Transfer Error Attributes Register */
> + __be32 ltear; /**< Transfer Error Address Register */
> + u8 res6[0xC];
> + __be32 lbcr; /**< Configuration Register */
> +#define LBCR_LDIS 0x80000000
> +#define LBCR_LDIS_SHIFT 31
> +#define LBCR_BCTLC 0x00C00000
> +#define LBCR_BCTLC_SHIFT 22
> +#define LBCR_AHD 0x00200000
> +#define LBCR_LPBSE 0x00020000
> +#define LBCR_LPBSE_SHIFT 17
> +#define LBCR_EPAR 0x00010000
> +#define LBCR_EPAR_SHIFT 16
> +#define LBCR_BMT 0x0000FF00
> +#define LBCR_BMT_SHIFT 8
> +#define LBCR_INIT 0x00040000
> + __be32 lcrr; /**< Clock Ratio Register */
> +#define LCRR_DBYP 0x80000000
> +#define LCRR_DBYP_SHIFT 31
> +#define LCRR_BUFCMDC 0x30000000
> +#define LCRR_BUFCMDC_SHIFT 28
> +#define LCRR_ECL 0x03000000
> +#define LCRR_ECL_SHIFT 24
> +#define LCRR_EADC 0x00030000
> +#define LCRR_EADC_SHIFT 16
> +#define LCRR_CLKDIV 0x0000000F
> +#define LCRR_CLKDIV_SHIFT 0
> + u8 res7[0x8];
> + __be32 fmr; /**< Flash Mode Register */
> +#define FMR_CWTO 0x0000F000
> +#define FMR_CWTO_SHIFT 12
> +#define FMR_BOOT 0x00000800
> +#define FMR_ECCM 0x00000100
> +#define FMR_AL 0x00000030
> +#define FMR_AL_SHIFT 4
> +#define FMR_OP 0x00000003
> +#define FMR_OP_SHIFT 0
> + __be32 fir; /**< Flash Instruction Register */
> +#define FIR_OP0 0xF0000000
> +#define FIR_OP0_SHIFT 28
> +#define FIR_OP1 0x0F000000
> +#define FIR_OP1_SHIFT 24
> +#define FIR_OP2 0x00F00000
> +#define FIR_OP2_SHIFT 20
> +#define FIR_OP3 0x000F0000
> +#define FIR_OP3_SHIFT 16
> +#define FIR_OP4 0x0000F000
> +#define FIR_OP4_SHIFT 12
> +#define FIR_OP5 0x00000F00
> +#define FIR_OP5_SHIFT 8
> +#define FIR_OP6 0x000000F0
> +#define FIR_OP6_SHIFT 4
> +#define FIR_OP7 0x0000000F
> +#define FIR_OP7_SHIFT 0
> +#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
> +#define FIR_OP_CA 0x1 /* Issue current column address */
> +#define FIR_OP_PA 0x2 /* Issue current block+page address
> */
> +#define FIR_OP_UA 0x3 /* Issue user defined address */
> +#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
> +#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
> +#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
> +#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
> +#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer
> */
> +#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
> +#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
> +#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
> +#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
> +#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
> +#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
> +#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
> + __be32 fcr; /**< Flash Command Register */
> +#define FCR_CMD0 0xFF000000
> +#define FCR_CMD0_SHIFT 24
> +#define FCR_CMD1 0x00FF0000
> +#define FCR_CMD1_SHIFT 16
> +#define FCR_CMD2 0x0000FF00
> +#define FCR_CMD2_SHIFT 8
> +#define FCR_CMD3 0x000000FF
> +#define FCR_CMD3_SHIFT 0
> + __be32 fbar; /**< Flash Block Address Register */
> +#define FBAR_BLK 0x00FFFFFF
> + __be32 fpar; /**< Flash Page Address Register */
> +#define FPAR_SP_PI 0x00007C00
> +#define FPAR_SP_PI_SHIFT 10
> +#define FPAR_SP_MS 0x00000200
> +#define FPAR_SP_CI 0x000001FF
> +#define FPAR_SP_CI_SHIFT 0
> +#define FPAR_LP_PI 0x0003F000
> +#define FPAR_LP_PI_SHIFT 12
> +#define FPAR_LP_MS 0x00000800
> +#define FPAR_LP_CI 0x000007FF
> +#define FPAR_LP_CI_SHIFT 0
> + __be32 fbcr; /**< Flash Byte Count Register */
> +#define FBCR_BC 0x00000FFF
> + u8 res11[0x8];
> + u8 res8[0xF00];
> +};
> +
> +#endif /* __ASM_FSL_LBC_H */
> --
> 1.5.2.2
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-03-11 17:24 ` [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs Anton Vorontsov
@ 2008-04-11 14:09 ` Kumar Gala
2008-04-11 16:13 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Kumar Gala @ 2008-04-11 14:09 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> These will be used by the FSL UPM NAND driver.
can this be a bit more descriptive. What exactly are these functions
trying to accomplish.
>
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/Kconfig | 5 ++
> arch/powerpc/sysdev/Makefile | 1 +
> arch/powerpc/sysdev/fsl_lbc.c | 99 ++++++++++++++++++++++++++++++++
> +++++++++
> include/asm-powerpc/fsl_lbc.h | 63 ++++++++++++++++++++++++++
> 4 files changed, 168 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index ef12db0..9c68592 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -491,6 +491,11 @@ config FSL_PCI
> bool
> select PPC_INDIRECT_PCI
>
> +config FSL_LBC
> + bool
> + help
> + Freescale Localbus support
> +
> # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
> config MCA
> bool
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/
> Makefile
> index 15f3e85..62b6ef0 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
> obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
> obj-$(CONFIG_FSL_SOC) += fsl_soc.o
> obj-$(CONFIG_FSL_PCI) += fsl_pci.o
> +obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
> obj-$(CONFIG_RAPIDIO) += fsl_rio.o
> obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
> obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
> diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/
> fsl_lbc.c
> new file mode 100644
> index 0000000..b59f2f4
> --- /dev/null
> +++ b/arch/powerpc/sysdev/fsl_lbc.c
> @@ -0,0 +1,99 @@
> +/*
> + * Freescale UPM routines.
> + *
> + * Copyright (c) 2007-2008 MontaVista Software, Inc.
> + *
> + * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <asm/fsl_lbc.h>
> +
> +spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
> +
> +struct fsl_lbc_regs __iomem *fsl_lbc_regs;
> +EXPORT_SYMBOL(fsl_lbc_regs);
> +
> +static char __initdata *compat_lbc[] = {
> + "fsl,pq2-localbus",
> + "fsl,pq2pro-localbus",
> + "fsl,pq3-localbus",
> + "fsl,elbc",
> +};
> +
> +static int __init fsl_lbc_init(void)
> +{
> + struct device_node *lbus;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
> + lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
> + if (lbus)
> + goto found;
> + }
> + return -ENODEV;
> +
> +found:
> + fsl_lbc_regs = of_iomap(lbus, 0);
> + of_node_put(lbus);
> + if (!fsl_lbc_regs)
> + return -ENOMEM;
> + return 0;
> +}
> +arch_initcall(fsl_lbc_init);
> +
> +int fsl_upm_find(u32 base, struct fsl_upm *upm)
what is base?
>
> +{
> + int i;
> + __be32 br;
> + __be32 or;
> +
> + if (!fsl_lbc_regs)
> + return -ENODEV;
> +
> + for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
> + br = in_be32(&fsl_lbc_regs->bank[i].br);
> + or = in_be32(&fsl_lbc_regs->bank[i].or);
> +
> + if (br & BR_V && (br & or & BR_BA) == base)
> + goto found;
> + }
> +
> + return -ENOENT;
> +found:
> + switch (br & BR_MSEL) {
> + case BR_MS_UPMA:
> + upm->mxmr = &fsl_lbc_regs->mamr;
> + break;
> + case BR_MS_UPMB:
> + upm->mxmr = &fsl_lbc_regs->mbmr;
> + break;
> + case BR_MS_UPMC:
> + upm->mxmr = &fsl_lbc_regs->mcmr;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + switch (br & BR_PS) {
> + case BR_PS_8:
> + upm->width = 8;
> + break;
> + case BR_PS_16:
> + upm->width = 16;
> + break;
> + case BR_PS_32:
> + upm->width = 32;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-04-11 14:09 ` Kumar Gala
@ 2008-04-11 16:13 ` Anton Vorontsov
2008-04-11 16:18 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-11 16:13 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
On Fri, Apr 11, 2008 at 09:09:57AM -0500, Kumar Gala wrote:
>
> On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
>> These will be used by the FSL UPM NAND driver.
>
> can this be a bit more descriptive. What exactly are these functions
> trying to accomplish.
Yeah, sorry about that. Here is updated patch, with a bit more descriptive
comment, and highly kernel-doc'ed functions.
>> +int fsl_upm_find(u32 base, struct fsl_upm *upm)
>
> what is base?
Address base, as in LBC Base address register. Fixed down below.
Thanks for looking into this.
- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [POWERPC] fsl_lbc: implement few UPM routines
Freescale UPM can be used to adjust localbus timings or to generate
orbitrary, pre-programmed "patterns" on the external Localbus signals.
This patch implements few routines so drivers could work with UPMs in
safe and generic manner.
So far there is just one user of these routines: Freescale UPM NAND
driver.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/Kconfig | 5 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 111 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/fsl_lbc.h | 87 ++++++++++++++++++++++++++++++++
4 files changed, 204 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ef12db0..9c68592 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,6 +491,11 @@ config FSL_PCI
bool
select PPC_INDIRECT_PCI
+config FSL_LBC
+ bool
+ help
+ Freescale Localbus support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 15f3e85..62b6ef0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
+obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 0000000..147e4e0
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,111 @@
+/*
+ * Freescale LBC and UPM routines.
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/fsl_lbc.h>
+
+spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+
+struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+EXPORT_SYMBOL(fsl_lbc_regs);
+
+static char __initdata *compat_lbc[] = {
+ "fsl,pq2-localbus",
+ "fsl,pq2pro-localbus",
+ "fsl,pq3-localbus",
+ "fsl,elbc",
+};
+
+static int __init fsl_lbc_init(void)
+{
+ struct device_node *lbus;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
+ lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
+ if (lbus)
+ goto found;
+ }
+ return -ENODEV;
+
+found:
+ fsl_lbc_regs = of_iomap(lbus, 0);
+ of_node_put(lbus);
+ if (!fsl_lbc_regs)
+ return -ENOMEM;
+ return 0;
+}
+arch_initcall(fsl_lbc_init);
+
+/**
+ * fsl_upm_find - find pre-programmed UPM via base address
+ * @addr_base: base address of the memory bank controlled by the UPM
+ * @upm: pointer to the allocated fsl_upm structure
+ *
+ * This function walks UPMs comparing "Base address" field of the BR registers
+ * with the supplied addr_base argument. When bases are match, this function
+ * fills fsl_upm structure so you can use it with the rest of UPM API. On
+ * success this function returns 0, otherwise it returns appropriate errno
+ * value.
+ */
+int fsl_upm_find(u32 addr_base, struct fsl_upm *upm)
+{
+ int i;
+ __be32 br;
+ __be32 or;
+
+ if (!fsl_lbc_regs)
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
+ br = in_be32(&fsl_lbc_regs->bank[i].br);
+ or = in_be32(&fsl_lbc_regs->bank[i].or);
+
+ if (br & BR_V && (br & or & BR_BA) == addr_base)
+ goto found;
+ }
+
+ return -ENOENT;
+found:
+ switch (br & BR_MSEL) {
+ case BR_MS_UPMA:
+ upm->mxmr = &fsl_lbc_regs->mamr;
+ break;
+ case BR_MS_UPMB:
+ upm->mxmr = &fsl_lbc_regs->mbmr;
+ break;
+ case BR_MS_UPMC:
+ upm->mxmr = &fsl_lbc_regs->mcmr;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (br & BR_PS) {
+ case BR_PS_8:
+ upm->width = 8;
+ break;
+ case BR_PS_16:
+ upm->width = 16;
+ break;
+ case BR_PS_32:
+ upm->width = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(fsl_upm_find);
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
index 13a3c28..960f781 100644
--- a/include/asm-powerpc/fsl_lbc.h
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -24,6 +24,8 @@
#define __ASM_FSL_LBC_H
#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
struct fsl_lbc_bank {
__be32 br; /**< Base Register */
@@ -98,6 +100,11 @@ struct fsl_lbc_regs {
__be32 mar; /**< UPM Address Register */
u8 res1[0x4];
__be32 mamr; /**< UPMA Mode Register */
+#define MxMR_OP_NO (0 << 28) /**< normal operation */
+#define MxMR_OP_WA (1 << 28) /**< write array */
+#define MxMR_OP_RA (2 << 28) /**< read array */
+#define MxMR_OP_RP (3 << 28) /**< run pattern */
+#define MxMR_MAD 0x3f /**< machine address */
__be32 mbmr; /**< UPMB Mode Register */
__be32 mcmr; /**< UPMC Mode Register */
u8 res2[0x8];
@@ -220,4 +227,84 @@ struct fsl_lbc_regs {
u8 res8[0xF00];
};
+extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+extern spinlock_t fsl_lbc_lock;
+
+/*
+ * FSL UPM routines
+ */
+struct fsl_upm {
+ __be32 __iomem *mxmr;
+ int width;
+};
+
+extern int fsl_upm_find(u32 addr_base, struct fsl_upm *upm);
+
+/**
+ * fsl_upm_start_pattern - start UPM patterns execution
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @pat_offset: UPM pattern offset for the command to be executed
+ *
+ * This routine programmes UPM so the next memory access that hits an UPM
+ * will trigger pattern execution, starting at pat_offset.
+ */
+static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
+{
+ clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
+}
+
+/**
+ * fsl_upm_end_pattern - end UPM patterns execution
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ *
+ * This routine reverts UPM to normal operation mode.
+ */
+static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
+{
+ clrbits32(upm->mxmr, MxMR_OP_RP);
+
+ while (in_be32(upm->mxmr) & MxMR_OP_RP)
+ cpu_relax();
+}
+
+/**
+ * fsl_upm_run_pattern - actually run an UPM pattern
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @io_base: remapped pointer to where memory access should happen
+ * @mar: MAR register content during pattern execution
+ *
+ * This function triggers dummy write to the memory specified by the io_base,
+ * thus UPM pattern actually executed. Note that mar usage depends on the
+ * pre-programmed AMX bits in the UPM RAM.
+ */
+static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
+ void __iomem *io_base, u32 mar)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+ out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+ switch (upm->width) {
+ case 8:
+ out_8(io_base, 0x0);
+ break;
+ case 16:
+ out_be16(io_base, 0x0);
+ break;
+ case 32:
+ out_be32(io_base, 0x0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+ return ret;
+}
+
#endif /* __ASM_FSL_LBC_H */
--
1.5.4.5
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-04-11 16:13 ` Anton Vorontsov
@ 2008-04-11 16:18 ` Scott Wood
2008-04-11 17:03 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-04-11 16:18 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
Anton Vorontsov wrote:
> On Fri, Apr 11, 2008 at 09:09:57AM -0500, Kumar Gala wrote:
>> On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
>>> These will be used by the FSL UPM NAND driver.
>> can this be a bit more descriptive. What exactly are these functions
>> trying to accomplish.
>
> Yeah, sorry about that. Here is updated patch, with a bit more descriptive
> comment, and highly kernel-doc'ed functions.
>
>>> +int fsl_upm_find(u32 base, struct fsl_upm *upm)
>> what is base?
>
> Address base, as in LBC Base address register. Fixed down below.
Should it be phys_addr_t?
> +/**
> + * fsl_upm_find - find pre-programmed UPM via base address
> + * @addr_base: base address of the memory bank controlled by the UPM
> + * @upm: pointer to the allocated fsl_upm structure
> + *
> + * This function walks UPMs comparing "Base address" field of the BR registers
> + * with the supplied addr_base argument. When bases are match, this function
> + * fills fsl_upm structure so you can use it with the rest of UPM API. On
> + * success this function returns 0, otherwise it returns appropriate errno
> + * value.
> + */
The FCM driver does something very similar; could we name this something
more generic such as fsl_lbc_find?
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-04-11 16:18 ` Scott Wood
@ 2008-04-11 17:03 ` Anton Vorontsov
2008-04-12 4:09 ` Paul Mackerras
2008-04-14 15:11 ` Kumar Gala
0 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-11 17:03 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Fri, Apr 11, 2008 at 11:18:30AM -0500, Scott Wood wrote:
> Anton Vorontsov wrote:
>> On Fri, Apr 11, 2008 at 09:09:57AM -0500, Kumar Gala wrote:
>>> On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
>>>> These will be used by the FSL UPM NAND driver.
>>> can this be a bit more descriptive. What exactly are these functions
>>> trying to accomplish.
>>
>> Yeah, sorry about that. Here is updated patch, with a bit more descriptive
>> comment, and highly kernel-doc'ed functions.
>>
>>>> +int fsl_upm_find(u32 base, struct fsl_upm *upm)
>>> what is base?
>>
>> Address base, as in LBC Base address register. Fixed down below.
>
> Should it be phys_addr_t?
Well, today I don't see much sense in this other than for documentation
purposes, this code is 32bit centric anyway. But ok, let's do it.
>> +/**
>> + * fsl_upm_find - find pre-programmed UPM via base address
>> + * @addr_base: base address of the memory bank controlled by the UPM
>> + * @upm: pointer to the allocated fsl_upm structure
>> + *
>> + * This function walks UPMs comparing "Base address" field of the BR registers
>> + * with the supplied addr_base argument. When bases are match, this function
>> + * fills fsl_upm structure so you can use it with the rest of UPM API. On
>> + * success this function returns 0, otherwise it returns appropriate errno
>> + * value.
>> + */
>
> The FCM driver does something very similar; could we name this something
> more generic such as fsl_lbc_find?
Ok. Updated patch follows.
Thanks!
- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [POWERPC] fsl_lbc: implement few UPM routines
Freescale UPM can be used to adjust localbus timings or to generate
orbitrary, pre-programmed "patterns" on the external Localbus signals.
This patch implements few routines so drivers could work with UPMs in
safe and generic manner.
So far there is just one user of these routines: Freescale UPM NAND
driver.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/Kconfig | 5 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 129 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/fsl_lbc.h | 88 ++++++++++++++++++++++++++++
4 files changed, 223 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ef12db0..9c68592 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,6 +491,11 @@ config FSL_PCI
bool
select PPC_INDIRECT_PCI
+config FSL_LBC
+ bool
+ help
+ Freescale Localbus support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 15f3e85..62b6ef0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
+obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 0000000..422c8fa
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,129 @@
+/*
+ * Freescale LBC and UPM routines.
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/fsl_lbc.h>
+
+spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+
+struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+EXPORT_SYMBOL(fsl_lbc_regs);
+
+static char __initdata *compat_lbc[] = {
+ "fsl,pq2-localbus",
+ "fsl,pq2pro-localbus",
+ "fsl,pq3-localbus",
+ "fsl,elbc",
+};
+
+static int __init fsl_lbc_init(void)
+{
+ struct device_node *lbus;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
+ lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
+ if (lbus)
+ goto found;
+ }
+ return -ENODEV;
+
+found:
+ fsl_lbc_regs = of_iomap(lbus, 0);
+ of_node_put(lbus);
+ if (!fsl_lbc_regs)
+ return -ENOMEM;
+ return 0;
+}
+arch_initcall(fsl_lbc_init);
+
+/**
+ * fsl_lbc_find - find Localbus bank
+ * @addr_base: base address of the memory bank
+ *
+ * This function walks LBC banks comparing "Base address" field of the BR
+ * registers with the supplied addr_base argument. When bases match this
+ * function returns bank number (starting with 0), otherwise it returns
+ * appropriate errno value.
+ */
+int fsl_lbc_find(phys_addr_t addr_base)
+{
+ int i;
+
+ if (!fsl_lbc_regs)
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
+ __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
+ __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+
+ if (br & BR_V && (br & or & BR_BA) == addr_base)
+ return i;
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL(fsl_lbc_find);
+
+/**
+ * fsl_upm_find - find pre-programmed UPM via base address
+ * @addr_base: base address of the memory bank controlled by the UPM
+ * @upm: pointer to the allocated fsl_upm structure
+ *
+ * This function fills fsl_upm structure so you can use it with the rest of
+ * UPM API. On success this function returns 0, otherwise it returns
+ * appropriate errno value.
+ */
+int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
+{
+ int bank;
+ __be32 br;
+
+ bank = fsl_lbc_find(addr_base);
+ if (bank < 0)
+ return bank;
+
+ br = in_be32(&fsl_lbc_regs->bank[bank].br);
+
+ switch (br & BR_MSEL) {
+ case BR_MS_UPMA:
+ upm->mxmr = &fsl_lbc_regs->mamr;
+ break;
+ case BR_MS_UPMB:
+ upm->mxmr = &fsl_lbc_regs->mbmr;
+ break;
+ case BR_MS_UPMC:
+ upm->mxmr = &fsl_lbc_regs->mcmr;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (br & BR_PS) {
+ case BR_PS_8:
+ upm->width = 8;
+ break;
+ case BR_PS_16:
+ upm->width = 16;
+ break;
+ case BR_PS_32:
+ upm->width = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(fsl_upm_find);
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
index 13a3c28..303f548 100644
--- a/include/asm-powerpc/fsl_lbc.h
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -24,6 +24,8 @@
#define __ASM_FSL_LBC_H
#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
struct fsl_lbc_bank {
__be32 br; /**< Base Register */
@@ -98,6 +100,11 @@ struct fsl_lbc_regs {
__be32 mar; /**< UPM Address Register */
u8 res1[0x4];
__be32 mamr; /**< UPMA Mode Register */
+#define MxMR_OP_NO (0 << 28) /**< normal operation */
+#define MxMR_OP_WA (1 << 28) /**< write array */
+#define MxMR_OP_RA (2 << 28) /**< read array */
+#define MxMR_OP_RP (3 << 28) /**< run pattern */
+#define MxMR_MAD 0x3f /**< machine address */
__be32 mbmr; /**< UPMB Mode Register */
__be32 mcmr; /**< UPMC Mode Register */
u8 res2[0x8];
@@ -220,4 +227,85 @@ struct fsl_lbc_regs {
u8 res8[0xF00];
};
+extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+extern spinlock_t fsl_lbc_lock;
+
+/*
+ * FSL UPM routines
+ */
+struct fsl_upm {
+ __be32 __iomem *mxmr;
+ int width;
+};
+
+extern int fsl_lbc_find(phys_addr_t addr_base);
+extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
+
+/**
+ * fsl_upm_start_pattern - start UPM patterns execution
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @pat_offset: UPM pattern offset for the command to be executed
+ *
+ * This routine programmes UPM so the next memory access that hits an UPM
+ * will trigger pattern execution, starting at pat_offset.
+ */
+static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
+{
+ clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
+}
+
+/**
+ * fsl_upm_end_pattern - end UPM patterns execution
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ *
+ * This routine reverts UPM to normal operation mode.
+ */
+static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
+{
+ clrbits32(upm->mxmr, MxMR_OP_RP);
+
+ while (in_be32(upm->mxmr) & MxMR_OP_RP)
+ cpu_relax();
+}
+
+/**
+ * fsl_upm_run_pattern - actually run an UPM pattern
+ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @io_base: remapped pointer to where memory access should happen
+ * @mar: MAR register content during pattern execution
+ *
+ * This function triggers dummy write to the memory specified by the io_base,
+ * thus UPM pattern actually executed. Note that mar usage depends on the
+ * pre-programmed AMX bits in the UPM RAM.
+ */
+static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
+ void __iomem *io_base, u32 mar)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+ out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+ switch (upm->width) {
+ case 8:
+ out_8(io_base, 0x0);
+ break;
+ case 16:
+ out_be16(io_base, 0x0);
+ break;
+ case 32:
+ out_be32(io_base, 0x0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+ return ret;
+}
+
#endif /* __ASM_FSL_LBC_H */
--
1.5.4.5
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-04-11 17:03 ` Anton Vorontsov
@ 2008-04-12 4:09 ` Paul Mackerras
2008-04-14 15:11 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Paul Mackerras @ 2008-04-12 4:09 UTC (permalink / raw)
To: avorontsov; +Cc: Scott Wood, linuxppc-dev
Anton Vorontsov writes:
> Ok. Updated patch follows.
>
> Thanks!
>
> - - - -
> From: Anton Vorontsov <avorontsov@ru.mvista.com>
> Subject: [POWERPC] fsl_lbc: implement few UPM routines
Just a hint: your patches are less likely to get overlooked if you
change the subject of your email to describe the new patch rather than
just leaving it as Re: some old patch.
Paul.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
2008-04-11 14:06 ` Kumar Gala
@ 2008-04-13 12:53 ` David Woodhouse
0 siblings, 0 replies; 47+ messages in thread
From: David Woodhouse @ 2008-04-13 12:53 UTC (permalink / raw)
To: Kumar Gala; +Cc: Scott Wood, linuxppc-dev@ozlabs.org list, linux-mtd
On Fri, 2008-04-11 at 09:06 -0500, Kumar Gala wrote:
>
> David, can you ack this. It looks good to me but want a MTD
> maintainer ack before having it go through the powerpc tree.
Looks sane to me.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
--
dwmw2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
2008-04-11 14:06 ` Kumar Gala
@ 2008-04-14 15:10 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:10 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: Scott Wood, linuxppc-dev, linux-mtd
On Mar 11, 2008, at 12:23 PM, Anton Vorontsov wrote:
> This is needed to support other localbus peripherals, such as
> NAND on FSL UPM.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
>
> Would be great if someone from the MTD community will ack this patch
> to go through powerpc trees.
>
> Thanks,
>
> drivers/mtd/nand/fsl_elbc_nand.c | 219 +
> +-----------------------------------
> include/asm-powerpc/fsl_lbc.h | 223 +++++++++++++++++++++++++++++
> +++++++++
> 2 files changed, 235 insertions(+), 207 deletions(-)
> create mode 100644 include/asm-powerpc/fsl_lbc.h
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
2008-04-11 17:03 ` Anton Vorontsov
2008-04-12 4:09 ` Paul Mackerras
@ 2008-04-14 15:11 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:11 UTC (permalink / raw)
To: avorontsov; +Cc: Scott Wood, linuxppc-dev
>
>
> Subject: [POWERPC] fsl_lbc: implement few UPM routines
>
> Freescale UPM can be used to adjust localbus timings or to generate
> orbitrary, pre-programmed "patterns" on the external Localbus signals.
> This patch implements few routines so drivers could work with UPMs in
> safe and generic manner.
>
> So far there is just one user of these routines: Freescale UPM NAND
> driver.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/Kconfig | 5 ++
> arch/powerpc/sysdev/Makefile | 1 +
> arch/powerpc/sysdev/fsl_lbc.c | 129 ++++++++++++++++++++++++++++++++
> +++++++++
> include/asm-powerpc/fsl_lbc.h | 88 ++++++++++++++++++++++++++++
> 4 files changed, 223 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset
2008-03-11 17:24 ` [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset Anton Vorontsov
2008-03-18 17:48 ` Scott Wood
@ 2008-04-14 15:11 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:11 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> qe_muram_offset is the reverse of the qe_muram_addr, will be
> used for the Freescale QE USB Host Controller driver.
>
> This patch also moves qe_muram_addr into the qe.h header, plus
> adds __iomem hints to use with sparse.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/sysdev/qe_lib/qe.c | 8 +-------
> include/asm-powerpc/immap_qe.h | 2 +-
> include/asm-powerpc/qe.h | 11 ++++++++++-
> 3 files changed, 12 insertions(+), 9 deletions(-)
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h
2008-03-11 17:24 ` [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h Anton Vorontsov
@ 2008-04-14 15:11 ` Kumar Gala
0 siblings, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:11 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> Headers should include prototypes they use, otherwise build will
> break if we use it without explicitly including io.h:
>
> CC arch/powerpc/sysdev/qe_lib/gtm.o
> In file included from include/asm/qe.h:20,
> from arch/powerpc/sysdev/qe_lib/gtm.c:18:
> include/asm/immap_qe.h: In function =E2=80=98immrbar_virt_to_phys=E2=80=99=
:
> include/asm/immap_qe.h:480: error: implicit declaration of function =E2=20=
> =80=98virt_to_phys=E2=80=99
> make[2]: *** [arch/powerpc/sysdev/qe_lib/gtm.o] Error 1
> make[1]: *** [arch/powerpc/sysdev/qe_lib] Error 2
>
> gtm.c needs qe.h (which includes immap_qe.h) to use qe_get_brg_clk().
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> include/asm-powerpc/immap_qe.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk()
2008-03-11 17:24 ` [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk() Anton Vorontsov
2008-03-11 18:36 ` Kumar Gala
@ 2008-04-14 15:11 ` Kumar Gala
1 sibling, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:11 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> qe_get_brg_clk() will be used by the fsl_gtm routines.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/sysdev/qe_lib/qe.c | 5 +++--
> include/asm-powerpc/qe.h | 1 +
> 2 files changed, 4 insertions(+), 2 deletions(-)
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings
2008-03-11 17:24 ` [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings Anton Vorontsov
@ 2008-04-14 15:12 ` Kumar Gala
0 siblings, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:12 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/sysdev/qe_lib/qe_io.c | 5 +++--
> 1 files changed, 3 insertions(+), 2 deletions(-)
applied.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 0/8] A bit of new code and sparse cleanups along the way
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
` (7 preceding siblings ...)
2008-03-11 17:24 ` [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings Anton Vorontsov
@ 2008-04-14 15:14 ` Kumar Gala
2008-04-14 17:49 ` Anton Vorontsov
8 siblings, 1 reply; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 15:14 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:21 PM, Anton Vorontsov wrote:
> Hi all,
>
> Please consider these patches for the 2.6.26.
I've applied most of these patches to my powerpc-next branch. The
following two patches have NOT been applied:
[POWERPC] sysdev,qe_lib: implement FSL GTM support
[POWERPC] qe_lib: add support for QE USB
It seemed there was rework required to the sysdev,qe_lib patch.
- k
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 0/8] A bit of new code and sparse cleanups along the way
2008-04-14 15:14 ` [PATCH 0/8] A bit of new code and sparse cleanups along the way Kumar Gala
@ 2008-04-14 17:49 ` Anton Vorontsov
0 siblings, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-14 17:49 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
On Mon, Apr 14, 2008 at 10:14:05AM -0500, Kumar Gala wrote:
>
> On Mar 11, 2008, at 12:21 PM, Anton Vorontsov wrote:
>> Hi all,
>>
>> Please consider these patches for the 2.6.26.
>
> I've applied most of these patches to my powerpc-next branch.
Thanks!
> The
> following two patches have NOT been applied:
>
> [POWERPC] sysdev,qe_lib: implement FSL GTM support
> [POWERPC] qe_lib: add support for QE USB
>
> It seemed there was rework required to the sysdev,qe_lib patch.
I can't recall any issues with "[POWERPC] qe_lib: add support for QE USB".
As for FSL GTM.. yes, I'll send updated version soon.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB
2008-03-11 17:24 ` [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB Anton Vorontsov
@ 2008-04-14 20:29 ` Kumar Gala
0 siblings, 0 replies; 47+ messages in thread
From: Kumar Gala @ 2008-04-14 20:29 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Mar 11, 2008, at 12:24 PM, Anton Vorontsov wrote:
> I believe QE USB clocks routing is qe_lib authority, so usb.c
> created. Also, now cmxgcr needs its own lock.
why? (I'm asking to be more descriptive in the commit message)
> This patch also fixes QE_USB_RESTART_TX command definition.
Patch look ok, but can you be a bit more descriptive about why we are
adding this.
- k
>
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/sysdev/qe_lib/Kconfig | 6 ++++
> arch/powerpc/sysdev/qe_lib/Makefile | 1 +
> arch/powerpc/sysdev/qe_lib/ucc.c | 7 ++--
> arch/powerpc/sysdev/qe_lib/usb.c | 57 ++++++++++++++++++++++++++
> +++++++++
> include/asm-powerpc/qe.h | 18 ++++++++++-
> 5 files changed, 85 insertions(+), 4 deletions(-)
> create mode 100644 arch/powerpc/sysdev/qe_lib/usb.c
>
> diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/
> sysdev/qe_lib/Kconfig
> index c1f2849..f09dae4 100644
> --- a/arch/powerpc/sysdev/qe_lib/Kconfig
> +++ b/arch/powerpc/sysdev/qe_lib/Kconfig
> @@ -25,3 +25,9 @@ config QE_GTM
> default y if FSL_GTM
> help
> QE General-purpose Timers Module support
> +
> +config QE_USB
> + bool
> + default y if USB_FHCI_HCD
> + help
> + QE USB Host Controller support
> diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/
> sysdev/qe_lib/Makefile
> index 3297a52..c666a59 100644
> --- a/arch/powerpc/sysdev/qe_lib/Makefile
> +++ b/arch/powerpc/sysdev/qe_lib/Makefile
> @@ -7,3 +7,4 @@ obj-$(CONFIG_UCC) += ucc.o
> obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
> obj-$(CONFIG_UCC_FAST) += ucc_fast.o
> obj-$(CONFIG_QE_GTM) += gtm.o
> +obj-$(CONFIG_QE_USB) += usb.o
> diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/
> qe_lib/ucc.c
> index 0e348d9..d3c7f5a 100644
> --- a/arch/powerpc/sysdev/qe_lib/ucc.c
> +++ b/arch/powerpc/sysdev/qe_lib/ucc.c
> @@ -26,7 +26,8 @@
> #include <asm/qe.h>
> #include <asm/ucc.h>
>
> -static DEFINE_SPINLOCK(ucc_lock);
> +DEFINE_SPINLOCK(cmxgcr_lock);
> +EXPORT_SYMBOL(cmxgcr_lock);
>
> int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
> {
> @@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
> if (ucc_num > UCC_MAX_NUM - 1)
> return -EINVAL;
>
> - spin_lock_irqsave(&ucc_lock, flags);
> + spin_lock_irqsave(&cmxgcr_lock, flags);
> clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
> ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
> - spin_unlock_irqrestore(&ucc_lock, flags);
> + spin_unlock_irqrestore(&cmxgcr_lock, flags);
>
> return 0;
> }
> diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/
> qe_lib/usb.c
> new file mode 100644
> index 0000000..60ce676
> --- /dev/null
> +++ b/arch/powerpc/sysdev/qe_lib/usb.c
> @@ -0,0 +1,57 @@
> +/*
> + * QE USB routines
> + *
> + * Copyright (c) Freescale Semicondutor, Inc. 2006.
> + * Shlomi Gridish <gridish@freescale.com>
> + * Jerry Huang <Chang-Ming.Huang@freescale.com>
> + * Copyright (c) MontaVista Software, Inc. 2008.
> + * Anton Vorontsov <avorontsov@ru.mvista.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <asm/immap_qe.h>
> +#include <asm/qe.h>
> +
> +int qe_usb_clock_set(enum qe_clock clk, int rate)
> +{
> + struct qe_mux __iomem *mux = &qe_immr->qmx;
> + unsigned long flags;
> + const bool is_brg = clk < QE_CLK1;
> + u32 val;
> +
> + switch (clk) {
> + case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
> + case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
> + case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
> + case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
> + case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
> + case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
> + case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
> + case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
> + case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
> + case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
> + default:
> + pr_err("%s: requested unknown clock %d\n", __func__, clk);
> + return -EINVAL;
> + }
> +
> + if (is_brg)
> + qe_setbrg(clk, rate, 1);
> +
> + spin_lock_irqsave(&cmxgcr_lock, flags);
> +
> + clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
> +
> + spin_unlock_irqrestore(&cmxgcr_lock, flags);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(qe_usb_clock_set);
> diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
> index c3be6e2..3276b06 100644
> --- a/include/asm-powerpc/qe.h
> +++ b/include/asm-powerpc/qe.h
> @@ -16,6 +16,7 @@
> #define _ASM_POWERPC_QE_H
> #ifdef __KERNEL__
>
> +#include <linux/spinlock.h>
> #include <asm/immap_qe.h>
>
> #define QE_NUM_OF_SNUM 28
> @@ -74,6 +75,8 @@ enum qe_clock {
> QE_CLK_DUMMY
> };
>
> +extern spinlock_t cmxgcr_lock;
> +
> /* Export QE common operations */
> extern void qe_reset(void);
> extern int par_io_init(struct device_node *np);
> @@ -156,6 +159,9 @@ int qe_upload_firmware(const struct qe_firmware
> *firmware);
> /* Obtain information on the uploaded firmware */
> struct qe_firmware_info *qe_get_firmware_info(void);
>
> +/* QE USB */
> +int qe_usb_clock_set(enum qe_clock clk, int rate);
> +
> /* Buffer descriptors */
> struct qe_bd {
> __be16 status;
> @@ -254,6 +260,16 @@ enum comm_dir {
> #define QE_CMXGCR_MII_ENET_MNG 0x00007000
> #define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
> #define QE_CMXGCR_USBCS 0x0000000f
> +#define QE_CMXGCR_USBCS_CLK3 0x1
> +#define QE_CMXGCR_USBCS_CLK5 0x2
> +#define QE_CMXGCR_USBCS_CLK7 0x3
> +#define QE_CMXGCR_USBCS_CLK9 0x4
> +#define QE_CMXGCR_USBCS_CLK13 0x5
> +#define QE_CMXGCR_USBCS_CLK17 0x6
> +#define QE_CMXGCR_USBCS_CLK19 0x7
> +#define QE_CMXGCR_USBCS_CLK21 0x8
> +#define QE_CMXGCR_USBCS_BRG9 0x9
> +#define QE_CMXGCR_USBCS_BRG10 0xa
>
> /* QE CECR Commands.
> */
> @@ -283,7 +299,7 @@ enum comm_dir {
> #define QE_HPAC_START_TX 0x0000060b
> #define QE_HPAC_START_RX 0x0000070b
> #define QE_USB_STOP_TX 0x0000000a
> -#define QE_USB_RESTART_TX 0x0000000b
> +#define QE_USB_RESTART_TX 0x0000000c
> #define QE_QMC_STOP_TX 0x0000000c
> #define QE_QMC_STOP_RX 0x0000000d
> #define QE_SS7_SU_FIL_RESET 0x0000000e
> --
> 1.5.2.2
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-03-18 20:48 ` Scott Wood
@ 2008-04-16 18:39 ` Anton Vorontsov
2008-04-16 18:44 ` Scott Wood
2008-04-17 14:23 ` Laurent Pinchart
0 siblings, 2 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-16 18:39 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Tue, Mar 18, 2008 at 03:48:12PM -0500, Scott Wood wrote:
[...]
> How about:
>
> struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
> int width);
>
> ...with np->data used by the caller to figure out which gtm pointer to
> pass in.
Thanks for the comments, I've tried to address them all.
Updated patch below (not for applying, still waiting for further
comments, if any).
- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [POWERPC] sysdev,qe_lib: implement FSL GTM support
GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts.
There are several limitations in this support:
1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
This is straightforward to implement when needed, two timers should
be marked as "requested" and configured as appropriate.
2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
This is also straightforward to implement when needed, all timers
should be marked as "requested" and configured as appropriate.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 32 +++-
arch/powerpc/Kconfig | 5 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_gtm.c | 322 ++++++++++++++++++++++++++
include/asm-powerpc/fsl_gtm.h | 106 +++++++++
5 files changed, 465 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index f19fe9f..ee14ecd 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,8 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Freescale General-purpose Timers Module
VII - Specifying interrupt information for devices
1) interrupts property
@@ -2795,6 +2796,35 @@ platforms are moved over to use the flattened-device-tree model.
big-endian;
};
+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+ GTMs).
+ - reg : should contain gtm registers location and length (0x40).
+ - interrupts : should contain four interrupts.
+ - interrupt-parent : interrupt source phandle.
+ - clock-frequency : specifies the frequency driving the timer.
+
+ Example:
+
+ timer@500 {
+ compatible = "fsl,gtm";
+ reg = <0x500 0x40>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
+ timer@440 {
+ compatible = "fsl,qe-gtm", "fsl,gtm";
+ reg = <0x440 0x40>;
+ interrupts = <12 13 14 15>;
+ interrupt-parent = <&qeic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
More devices will be defined as this spec matures.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 00c5e79..dd30ea4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -520,6 +520,11 @@ config FSL_LBC
help
Freescale Localbus support
+config FSL_GTM
+ bool
+ help
+ Freescale General-purpose Timers support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 42b44a1..3974412 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
+obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
new file mode 100644
index 0000000..6d86983
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,322 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <asm/fsl_gtm.h>
+
+/**
+ * gtm_get_timer - request GTM timer to use it with the rest of GTM API
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_timer(int width)
+{
+ struct device_node *np;
+ struct gtm *gtm = NULL;
+ int i;
+
+ if (width != 16)
+ return ERR_PTR(-ENOSYS);
+
+ for_each_compatible_node(np, NULL, "fsl,gtm") {
+ if (!np->data) {
+ WARN_ON(1);
+ continue;
+ }
+ gtm = np->data;
+
+ spin_lock_irq(>m->lock);
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ if (!gtm->timers[i].requested) {
+ gtm->timers[i].requested = true;
+ spin_unlock_irq(>m->lock);
+ of_node_put(np);
+ return >m->timers[i];
+ }
+ }
+
+ spin_unlock_irq(>m->lock);
+ }
+
+ if (gtm)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);
+
+/**
+ * gtm_get_specific_timer - request specific GTM timer
+ * @gtm: specific GTM, pass here GTM's device_node->data
+ * @timer: specific timer number, Timer1 is 0.
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer, int width)
+{
+ struct gtm_timer *ret = ERR_PTR(-EBUSY);
+
+ if (width != 16)
+ return ERR_PTR(-ENOSYS);
+
+ spin_lock_irq(>m->lock);
+
+ if (gtm->timers[timer].requested)
+ goto out;
+
+ ret = >m->timers[timer];
+ ret->requested = true;
+
+out:
+ spin_unlock_irq(>m->lock);
+ return ret;
+}
+EXPORT_SYMBOL(gtm_get_specific_timer);
+
+/**
+ * gtm_put_timer - release GTM timer
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function releases GTM timer so others may request it.
+ */
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+ spin_lock_irq(&tmr->gtm->lock);
+
+ tmr->requested = false;
+
+ spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+/*
+ * This is back-end for the exported functions, it's used to reset single
+ * timer in reference mode.
+ */
+static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
+ int reference_value, bool free_run)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned int prescaler;
+ u8 iclk = GTMDR_ICLK_ICLK;
+ u8 psr;
+ u8 sps;
+ unsigned long flags;
+
+ prescaler = gtm->clock / frequency;
+ /*
+ * We have two 8 bit prescalers -- primary and secondary (psr, sps),
+ * plus "slow go" mode (clk / 16). So, total prescale value is
+ * 16 * (psr + 1) * (sps + 1).
+ */
+ if (prescaler > 256 * 256 * 16)
+ return -EINVAL;
+
+ if (prescaler > 256 * 256) {
+ iclk = GTMDR_ICLK_SLGO;
+ prescaler /= 16;
+ }
+
+ if (prescaler > 256) {
+ psr = 256 - 1;
+ sps = prescaler / 256 - 1;
+ } else {
+ psr = prescaler - 1;
+ sps = 1 - 1;
+ }
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ /*
+ * Properly reset timers: stop, reset, set up prescalers, reference
+ * value and clear event register.
+ */
+ clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
+ GTCFR_STP(num) | GTCFR_RST(num));
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ out_be16(tmr->gtpsr, psr);
+ clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
+ GTMDR_ORI | (free_run ? GTMDR_FFR : 0));
+ out_be16(tmr->gtcnr, 0);
+ out_be16(tmr->gtrfr, reference_value);
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ /* Let it be. */
+ clrbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ spin_unlock_irqrestore(>m->lock, flags);
+
+ return 0;
+}
+
+/**
+ * gtm_reset_utimer16 - reset 16 bits timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @usec: timer interval in microseconds
+ * @free_run: free run flag
+ *
+ * This function (re)sets GTM timer so it counts up to the interval value and
+ * fires the interrupt when the value is reached. If free_run flag was set,
+ * timer will also reset itself upon reference value, otherwise it continues to
+ * increment.
+ */
+int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool free_run)
+{
+ /* quite obvious, frequency which is enough for µSec precision */
+ const int freq = 1000000;
+
+ /*
+ * We can lower the frequency (and probably power consumption) by
+ * dividing both frequency and usec by 2 until there is no remainder.
+ * But we won't bother with this unless savings are measured, so just
+ * run the timer as is.
+ */
+
+ return gtm_reset_ref_timer16(tmr, freq, usec, free_run);
+}
+EXPORT_SYMBOL(gtm_reset_utimer16);
+
+/**
+ * gtm_stop_timer16 - stop single timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * This function simply stops the GTM timer.
+ */
+void gtm_stop_timer16(struct gtm_timer *tmr)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned long flags;
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ spin_unlock_irqrestore(>m->lock, flags);
+}
+EXPORT_SYMBOL(gtm_stop_timer16);
+
+static void __init gtm_set_shortcuts(struct gtm_timer *timers,
+ struct gtm_timers_regs __iomem *regs)
+{
+ /*
+ * Yeah, I don't like this either, but timers' registers a bit messed,
+ * so we have to provide shortcuts to write timer independent code.
+ * Alternative option is to create gt*() accessors, but that will be
+ * even uglier and cryptic.
+ */
+ timers[0].gtcfr = ®s->gtcfr1;
+ timers[0].gtmdr = ®s->gtmdr1;
+ timers[0].gtpsr = ®s->gtpsr1;
+ timers[0].gtcnr = ®s->gtcnr1;
+ timers[0].gtrfr = ®s->gtrfr1;
+ timers[0].gtevr = ®s->gtevr1;
+
+ timers[1].gtcfr = ®s->gtcfr1;
+ timers[1].gtmdr = ®s->gtmdr2;
+ timers[1].gtpsr = ®s->gtpsr2;
+ timers[1].gtcnr = ®s->gtcnr2;
+ timers[1].gtrfr = ®s->gtrfr2;
+ timers[1].gtevr = ®s->gtevr2;
+
+ timers[2].gtcfr = ®s->gtcfr2;
+ timers[2].gtmdr = ®s->gtmdr3;
+ timers[2].gtpsr = ®s->gtpsr3;
+ timers[2].gtcnr = ®s->gtcnr3;
+ timers[2].gtrfr = ®s->gtrfr3;
+ timers[2].gtevr = ®s->gtevr3;
+
+ timers[3].gtcfr = ®s->gtcfr2;
+ timers[3].gtmdr = ®s->gtmdr4;
+ timers[3].gtpsr = ®s->gtpsr4;
+ timers[3].gtcnr = ®s->gtcnr4;
+ timers[3].gtrfr = ®s->gtrfr4;
+ timers[3].gtevr = ®s->gtevr4;
+}
+
+static int __init gtm_init(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,gtm") {
+ int i;
+ struct gtm *gtm;
+ const u32 *clock;
+ int size;
+
+ gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+ if (!gtm) {
+ pr_err("%s: unable to allocate memory\n",
+ np->full_name);
+ continue;
+ }
+
+ spin_lock_init(>m->lock);
+
+ clock = of_get_property(np, "clock-frequency", &size);
+ if (!clock || size != sizeof(*clock)) {
+ pr_err("%s: no clock-frequency\n", np->full_name);
+ goto err;
+ }
+ gtm->clock = *clock;
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ int ret;
+ struct resource irq;
+
+ ret = of_irq_to_resource(np, i, &irq);
+ if (ret == NO_IRQ) {
+ pr_err("%s: not enough interrupts specified\n",
+ np->full_name);
+ goto err;
+ }
+ gtm->timers[i].irq = irq.start;
+ gtm->timers[i].gtm = gtm;
+ }
+
+ gtm->regs = of_iomap(np, 0);
+ if (!gtm->regs) {
+ pr_err("%s: unable to iomap registers\n",
+ np->full_name);
+ goto err;
+ }
+
+ gtm_set_shortcuts(gtm->timers, gtm->regs);
+
+ /* We don't want to lose the node and its ->data */
+ of_node_get(np);
+ np->data = gtm;
+
+ continue;
+err:
+ kfree(gtm);
+ }
+ return 0;
+}
+arch_initcall(gtm_init);
diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm.h
new file mode 100644
index 0000000..46c02e7
--- /dev/null
+++ b/include/asm-powerpc/fsl_gtm.h
@@ -0,0 +1,106 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0)
+
+#define GTMDR_ICLK_MASK (3 << 1)
+#define GTMDR_ICLK_ICAS (0 << 1)
+#define GTMDR_ICLK_ICLK (1 << 1)
+#define GTMDR_ICLK_SLGO (2 << 1)
+#define GTMDR_FFR (1 << 3)
+#define GTMDR_ORI (1 << 4)
+#define GTMDR_SPS(x) ((x) << 8)
+
+struct gtm_timers_regs {
+ u8 gtcfr1; /* Timer 1, Timer 2 global config register */
+ u8 res0[0x3];
+ u8 gtcfr2; /* Timer 3, timer 4 global config register */
+ u8 res1[0xB];
+ __be16 gtmdr1; /* Timer 1 mode register */
+ __be16 gtmdr2; /* Timer 2 mode register */
+ __be16 gtrfr1; /* Timer 1 reference register */
+ __be16 gtrfr2; /* Timer 2 reference register */
+ __be16 gtcpr1; /* Timer 1 capture register */
+ __be16 gtcpr2; /* Timer 2 capture register */
+ __be16 gtcnr1; /* Timer 1 counter */
+ __be16 gtcnr2; /* Timer 2 counter */
+ __be16 gtmdr3; /* Timer 3 mode register */
+ __be16 gtmdr4; /* Timer 4 mode register */
+ __be16 gtrfr3; /* Timer 3 reference register */
+ __be16 gtrfr4; /* Timer 4 reference register */
+ __be16 gtcpr3; /* Timer 3 capture register */
+ __be16 gtcpr4; /* Timer 4 capture register */
+ __be16 gtcnr3; /* Timer 3 counter */
+ __be16 gtcnr4; /* Timer 4 counter */
+ __be16 gtevr1; /* Timer 1 event register */
+ __be16 gtevr2; /* Timer 2 event register */
+ __be16 gtevr3; /* Timer 3 event register */
+ __be16 gtevr4; /* Timer 4 event register */
+ __be16 gtpsr1; /* Timer 1 prescale register */
+ __be16 gtpsr2; /* Timer 2 prescale register */
+ __be16 gtpsr3; /* Timer 3 prescale register */
+ __be16 gtpsr4; /* Timer 4 prescale register */
+ u8 res2[0x40];
+} __attribute__ ((packed));
+
+struct gtm_timer {
+ unsigned int irq;
+
+ struct gtm *gtm;
+ bool requested;
+ u8 __iomem *gtcfr;
+ __be16 __iomem *gtmdr;
+ __be16 __iomem *gtpsr;
+ __be16 __iomem *gtcnr;
+ __be16 __iomem *gtrfr;
+ __be16 __iomem *gtevr;
+};
+
+struct gtm {
+ unsigned int clock;
+ struct gtm_timers_regs __iomem *regs;
+ struct gtm_timer timers[4];
+ spinlock_t lock;
+};
+
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
+ int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool free_run);
+extern void gtm_stop_timer16(struct gtm_timer *tmr);
+
+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @events: events mask to ack
+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16 events)
+{
+ out_be16(tmr->gtevr, events);
+}
+
+#endif /* __ASM_FSL_GTM_H */
--
1.5.5
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-16 18:39 ` Anton Vorontsov
@ 2008-04-16 18:44 ` Scott Wood
2008-04-16 21:00 ` Anton Vorontsov
2008-04-17 14:23 ` Laurent Pinchart
1 sibling, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-04-16 18:44 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Wed, Apr 16, 2008 at 10:39:04PM +0400, Anton Vorontsov wrote:
> +/**
> + * gtm_reset_utimer16 - reset 16 bits timer
> + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> + * @usec: timer interval in microseconds
> + * @free_run: free run flag
> + *
> + * This function (re)sets GTM timer so it counts up to the interval value and
> + * fires the interrupt when the value is reached. If free_run flag was set,
> + * timer will also reset itself upon reference value, otherwise it continues to
> + * increment.
> + */
> +int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool free_run)
A maximal timeout of ~65 ms is a little low... For use as a wakeup from
sleep mode, I'd like to be able to request timeouts as large as the
hardware allows.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-16 18:44 ` Scott Wood
@ 2008-04-16 21:00 ` Anton Vorontsov
2008-04-16 21:58 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-16 21:00 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Wed, Apr 16, 2008 at 01:44:42PM -0500, Scott Wood wrote:
> On Wed, Apr 16, 2008 at 10:39:04PM +0400, Anton Vorontsov wrote:
> > +/**
> > + * gtm_reset_utimer16 - reset 16 bits timer
> > + * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> > + * @usec: timer interval in microseconds
> > + * @free_run: free run flag
> > + *
> > + * This function (re)sets GTM timer so it counts up to the interval value and
> > + * fires the interrupt when the value is reached. If free_run flag was set,
> > + * timer will also reset itself upon reference value, otherwise it continues to
> > + * increment.
> > + */
> > +int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool free_run)
>
> A maximal timeout of ~65 ms is a little low... For use as a wakeup from
> sleep mode, I'd like to be able to request timeouts as large as the
> hardware allows.
That is about precision. You just need to implement gtm_reset_stimer()
is you want precision with a seconds, this will run a timer at 1 Hz.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-16 21:00 ` Anton Vorontsov
@ 2008-04-16 21:58 ` Scott Wood
2008-04-17 12:52 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-04-16 21:58 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Thu, Apr 17, 2008 at 01:00:42AM +0400, Anton Vorontsov wrote:
> On Wed, Apr 16, 2008 at 01:44:42PM -0500, Scott Wood wrote:
> > A maximal timeout of ~65 ms is a little low... For use as a wakeup from
> > sleep mode, I'd like to be able to request timeouts as large as the
> > hardware allows.
>
> That is about precision. You just need to implement gtm_reset_stimer()
> is you want precision with a seconds, this will run a timer at 1 Hz.
Enh. I'm not crazy about having to call separately named functions,
rather than have the timer code set the reference clock to the highest
precision that has the needed range.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-16 21:58 ` Scott Wood
@ 2008-04-17 12:52 ` Anton Vorontsov
2008-04-17 14:19 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-17 12:52 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Wed, Apr 16, 2008 at 04:58:21PM -0500, Scott Wood wrote:
> On Thu, Apr 17, 2008 at 01:00:42AM +0400, Anton Vorontsov wrote:
> > On Wed, Apr 16, 2008 at 01:44:42PM -0500, Scott Wood wrote:
> > > A maximal timeout of ~65 ms is a little low... For use as a wakeup from
> > > sleep mode, I'd like to be able to request timeouts as large as the
> > > hardware allows.
> >
> > That is about precision. You just need to implement gtm_reset_stimer()
> > is you want precision with a seconds, this will run a timer at 1 Hz.
>
> Enh. I'm not crazy about having to call separately named functions,
> rather than have the timer code set the reference clock to the highest
> precision that has the needed range.
Heh. Scott, think about it. You have single 16bit timer with variable
frequency. To use it, you'd better know what exactly precision you need.
Then you limited to u16 for the interval for this chosen precision.
Yes, you can implement this:
#define MAX_PRESCALER (256 * 256 * 16)
int gtm_reset_weird_behaving_utimer16(struct gtm_timer *tmr,
unsigned long long usec,
bool free_run)
{
int freq = 1000000;
int min_hz2 = (tmr->gtm->freq / MAX_PRESCALER) << 1;
while (!(freq & 1) && !(usec & 1) && freq >= min_hz2) {
freq >>= 1;
usec >>= 1;
}
if (usec > 0xffff)
return -EINVAL;
return gtm_reset_ref_timer16(tmr, freq, (u16)usec, free_run);
}
This function (depending on clock-frequency) will work for 1001 usecs,
but will return -EINVAL for 1000001 usecs, thought it will work for
1000000 usecs, and for 333000000 it will work too, but will again
return -EINVAL for 333000010 usecs. I hope this pattern is obvious.
This is really weird behaving, isn't it?
Oh, and later you can drop the 16 suffix and implement the dynamically
chosen cascading, depending if usec argument fits into single/double/quad
timer.
Though, I don't need all this stuff in the FHCI irq handlers, I do know
the precision I want. Like the most of kernel code does.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 12:52 ` Anton Vorontsov
@ 2008-04-17 14:19 ` Scott Wood
2008-04-17 15:07 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-04-17 14:19 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
On Thu, Apr 17, 2008 at 04:52:35PM +0400, Anton Vorontsov wrote:
> Heh. Scott, think about it. You have single 16bit timer with variable
> frequency. To use it, you'd better know what exactly precision you need.
Why? I know the timeout I need.
> Then you limited to u16 for the interval for this chosen precision.
>
> Yes, you can implement this:
>
> #define MAX_PRESCALER (256 * 256 * 16)
>
> int gtm_reset_weird_behaving_utimer16(struct gtm_timer *tmr,
> unsigned long long usec,
> bool free_run)
> {
> int freq = 1000000;
> int min_hz2 = (tmr->gtm->freq / MAX_PRESCALER) << 1;
>
> while (!(freq & 1) && !(usec & 1) && freq >= min_hz2) {
> freq >>= 1;
> usec >>= 1;
> }
>
> if (usec > 0xffff)
> return -EINVAL;
>
> return gtm_reset_ref_timer16(tmr, freq, (u16)usec, free_run);
> }
Try something like this:
int gtm_reset_sane_behaving_timer(struct gtm_timer *tmr,
u64 usec, bool free_run)
{
int freq = 1000000;
int min_hz2 = (tmr->gtm->freq / MAX_PRESCALER) << 1;
while (usec > 0xffff && freq >= min_hz2) {
freq >>= 1;
usec >>= 1;
}
if (usec > 0xffff)
return -EINVAL;
return gtm_reset_ref_timer16(tmr, freq, usec, free_run);
}
It could be made faster using cntlzw.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-16 18:39 ` Anton Vorontsov
2008-04-16 18:44 ` Scott Wood
@ 2008-04-17 14:23 ` Laurent Pinchart
2008-04-17 15:13 ` Anton Vorontsov
2008-04-17 16:12 ` Anton Vorontsov
1 sibling, 2 replies; 47+ messages in thread
From: Laurent Pinchart @ 2008-04-17 14:23 UTC (permalink / raw)
To: linuxppc-dev, avorontsov; +Cc: Scott Wood
[-- Attachment #1: Type: text/plain, Size: 3745 bytes --]
On Wednesday 16 April 2008 20:39, Anton Vorontsov wrote:
> On Tue, Mar 18, 2008 at 03:48:12PM -0500, Scott Wood wrote:
> [...]
> > How about:
> >
> > struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
> > int width);
> >
> > ...with np->data used by the caller to figure out which gtm pointer to
> > pass in.
>
> Thanks for the comments, I've tried to address them all.
>
> Updated patch below (not for applying, still waiting for further
> comments, if any).
>
> - - - -
> From: Anton Vorontsov <avorontsov@ru.mvista.com>
> Subject: [POWERPC] sysdev,qe_lib: implement FSL GTM support
>
> GTM stands for General-purpose Timers Module and able to generate
> timer{1,2,3,4} interrupts.
>
> There are several limitations in this support:
> 1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
> This is straightforward to implement when needed, two timers should
> be marked as "requested" and configured as appropriate.
> 2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
> This is also straightforward to implement when needed, all timers
> should be marked as "requested" and configured as appropriate.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> Documentation/powerpc/booting-without-of.txt | 32 +++-
> arch/powerpc/Kconfig | 5 +
> arch/powerpc/sysdev/Makefile | 1 +
> arch/powerpc/sysdev/fsl_gtm.c | 322 ++++++++++++++++++++++++++
> include/asm-powerpc/fsl_gtm.h | 106 +++++++++
> 5 files changed, 465 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
> create mode 100644 include/asm-powerpc/fsl_gtm.h
[snip]
> +/*
> + * This is back-end for the exported functions, it's used to reset single
> + * timer in reference mode.
> + */
> +static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
> + int reference_value, bool free_run)
> +{
> + struct gtm *gtm = tmr->gtm;
> + int num = tmr - >m->timers[0];
> + unsigned int prescaler;
> + u8 iclk = GTMDR_ICLK_ICLK;
> + u8 psr;
> + u8 sps;
> + unsigned long flags;
> +
> + prescaler = gtm->clock / frequency;
> + /*
> + * We have two 8 bit prescalers -- primary and secondary (psr, sps),
> + * plus "slow go" mode (clk / 16). So, total prescale value is
> + * 16 * (psr + 1) * (sps + 1).
> + */
> + if (prescaler > 256 * 256 * 16)
> + return -EINVAL;
> +
> + if (prescaler > 256 * 256) {
> + iclk = GTMDR_ICLK_SLGO;
> + prescaler /= 16;
> + }
> +
> + if (prescaler > 256) {
> + psr = 256 - 1;
> + sps = prescaler / 256 - 1;
> + } else {
> + psr = prescaler - 1;
> + sps = 1 - 1;
> + }
Don't forget that the CPM2 doesn't support the primary prescaler.
> + spin_lock_irqsave(>m->lock, flags);
> +
> + /*
> + * Properly reset timers: stop, reset, set up prescalers, reference
> + * value and clear event register.
> + */
> + clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
> + GTCFR_STP(num) | GTCFR_RST(num));
> +
> + setbits8(tmr->gtcfr, GTCFR_STP(num));
> +
> + out_be16(tmr->gtpsr, psr);
> + clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
> + GTMDR_ORI | (free_run ? GTMDR_FFR : 0));
> + out_be16(tmr->gtcnr, 0);
> + out_be16(tmr->gtrfr, reference_value);
> + out_be16(tmr->gtevr, 0xFFFF);
> +
> + /* Let it be. */
> + clrbits8(tmr->gtcfr, GTCFR_STP(num));
> +
> + spin_unlock_irqrestore(>m->lock, flags);
> +
> + return 0;
> +}
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 14:19 ` Scott Wood
@ 2008-04-17 15:07 ` Anton Vorontsov
2008-04-17 16:14 ` Scott Wood
0 siblings, 1 reply; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-17 15:07 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Thu, Apr 17, 2008 at 09:19:03AM -0500, Scott Wood wrote:
> On Thu, Apr 17, 2008 at 04:52:35PM +0400, Anton Vorontsov wrote:
> > Heh. Scott, think about it. You have single 16bit timer with variable
> > frequency. To use it, you'd better know what exactly precision you need.
>
> Why? I know the timeout I need.
>
> > Then you limited to u16 for the interval for this chosen precision.
> >
> > Yes, you can implement this:
> >
> > #define MAX_PRESCALER (256 * 256 * 16)
> >
> > int gtm_reset_weird_behaving_utimer16(struct gtm_timer *tmr,
> > unsigned long long usec,
> > bool free_run)
> > {
> > int freq = 1000000;
> > int min_hz2 = (tmr->gtm->freq / MAX_PRESCALER) << 1;
> >
> > while (!(freq & 1) && !(usec & 1) && freq >= min_hz2) {
> > freq >>= 1;
> > usec >>= 1;
> > }
> >
> > if (usec > 0xffff)
> > return -EINVAL;
> >
> > return gtm_reset_ref_timer16(tmr, freq, (u16)usec, free_run);
> > }
>
> Try something like this:
>
> int gtm_reset_sane_behaving_timer(struct gtm_timer *tmr,
> u64 usec, bool free_run)
> {
> int freq = 1000000;
> int min_hz2 = (tmr->gtm->freq / MAX_PRESCALER) << 1;
>
> while (usec > 0xffff && freq >= min_hz2) {
This isn't a timer with usec precision! This is a timer that silently
crops precision as it wants to. Ahh, I see you dropped "u" prefix.
Well. I'm not going to use it anyway, so just give it some name you
prefer and I'll wrap it into the patch. Preferably, drop a line here with
kerneldoc for it, so I'll not have to document its drawbacks. :-)
> freq >>= 1;
> usec >>= 1;
> }
>
> if (usec > 0xffff)
> return -EINVAL;
>
> return gtm_reset_ref_timer16(tmr, freq, usec, free_run);
> }
>
> It could be made faster using cntlzw.
No need to cntlzw, there is fls() already. Though, here you'll need
two because of u64.
Btw, I hope you aware that single GTM timer running at 166MHz will give you
6 minutes of sleep, maximum. With cascaded timer you'll get much better
result of 310 days. Is that possible to use cascaded timer as a wakeup
event on 8313? If so, I'd suggest you to implement cascading firstly.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 14:23 ` Laurent Pinchart
@ 2008-04-17 15:13 ` Anton Vorontsov
2008-04-17 16:12 ` Anton Vorontsov
1 sibling, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-17 15:13 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Scott Wood, linuxppc-dev
On Thu, Apr 17, 2008 at 04:23:56PM +0200, Laurent Pinchart wrote:
[...]
> > + /*
> > + * We have two 8 bit prescalers -- primary and secondary (psr, sps),
> > + * plus "slow go" mode (clk / 16). So, total prescale value is
> > + * 16 * (psr + 1) * (sps + 1).
> > + */
> > + if (prescaler > 256 * 256 * 16)
> > + return -EINVAL;
> > +
> > + if (prescaler > 256 * 256) {
> > + iclk = GTMDR_ICLK_SLGO;
> > + prescaler /= 16;
> > + }
> > +
> > + if (prescaler > 256) {
> > + psr = 256 - 1;
> > + sps = prescaler / 256 - 1;
> > + } else {
> > + psr = prescaler - 1;
> > + sps = 1 - 1;
> > + }
>
> Don't forget that the CPM2 doesn't support the primary prescaler.
I didn't know that, how can I possibly forget it? Oh, now I can.
Thanks for the info. :-)
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 14:23 ` Laurent Pinchart
2008-04-17 15:13 ` Anton Vorontsov
@ 2008-04-17 16:12 ` Anton Vorontsov
1 sibling, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-17 16:12 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Scott Wood, linuxppc-dev
On Thu, Apr 17, 2008 at 04:23:56PM +0200, Laurent Pinchart wrote:
> > + /*
> > + * We have two 8 bit prescalers -- primary and secondary (psr, sps),
> > + * plus "slow go" mode (clk / 16). So, total prescale value is
> > + * 16 * (psr + 1) * (sps + 1).
> > + */
> > + if (prescaler > 256 * 256 * 16)
> > + return -EINVAL;
> > +
> > + if (prescaler > 256 * 256) {
> > + iclk = GTMDR_ICLK_SLGO;
> > + prescaler /= 16;
> > + }
> > +
> > + if (prescaler > 256) {
> > + psr = 256 - 1;
> > + sps = prescaler / 256 - 1;
> > + } else {
> > + psr = prescaler - 1;
> > + sps = 1 - 1;
> > + }
>
> Don't forget that the CPM2 doesn't support the primary prescaler.
Here is incremental diff of how this is solved. I guess this should work.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index b0ddd54..b89c56d 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2835,7 +2835,7 @@ platforms are moved over to use the flattened-device-tree model.
Required properties:
- compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
- GTMs).
+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).
- reg : should contain gtm registers location and length (0x40).
- interrupts : should contain four interrupts.
- interrupt-parent : interrupt source phandle.
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 6d86983..105c633 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -125,27 +125,32 @@ static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
u8 psr;
u8 sps;
unsigned long flags;
+ int max_prescaler = 256 * 256 * 16;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!tmr->gtpsr)
+ max_prescaler /= 256;
prescaler = gtm->clock / frequency;
/*
* We have two 8 bit prescalers -- primary and secondary (psr, sps),
* plus "slow go" mode (clk / 16). So, total prescale value is
- * 16 * (psr + 1) * (sps + 1).
+ * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr.
*/
- if (prescaler > 256 * 256 * 16)
+ if (prescaler > max_prescaler)
return -EINVAL;
- if (prescaler > 256 * 256) {
+ if (prescaler > max_prescaler / 16) {
iclk = GTMDR_ICLK_SLGO;
prescaler /= 16;
}
- if (prescaler > 256) {
+ if (prescaler <= 256) {
+ psr = 0;
+ sps = prescaler - 1;
+ } else {
psr = 256 - 1;
sps = prescaler / 256 - 1;
- } else {
- psr = prescaler - 1;
- sps = 1 - 1;
}
spin_lock_irqsave(>m->lock, flags);
@@ -159,7 +164,8 @@ static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
setbits8(tmr->gtcfr, GTCFR_STP(num));
- out_be16(tmr->gtpsr, psr);
+ if (tmr->gtpsr)
+ out_be16(tmr->gtpsr, psr);
clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
GTMDR_ORI | (free_run ? GTMDR_FFR : 0));
out_be16(tmr->gtcnr, 0);
@@ -222,7 +228,8 @@ void gtm_stop_timer16(struct gtm_timer *tmr)
}
EXPORT_SYMBOL(gtm_stop_timer16);
-static void __init gtm_set_shortcuts(struct gtm_timer *timers,
+static void __init gtm_set_shortcuts(struct device_node *np,
+ struct gtm_timer *timers,
struct gtm_timers_regs __iomem *regs)
{
/*
@@ -233,31 +240,35 @@ static void __init gtm_set_shortcuts(struct gtm_timer *timers,
*/
timers[0].gtcfr = ®s->gtcfr1;
timers[0].gtmdr = ®s->gtmdr1;
- timers[0].gtpsr = ®s->gtpsr1;
timers[0].gtcnr = ®s->gtcnr1;
timers[0].gtrfr = ®s->gtrfr1;
timers[0].gtevr = ®s->gtevr1;
timers[1].gtcfr = ®s->gtcfr1;
timers[1].gtmdr = ®s->gtmdr2;
- timers[1].gtpsr = ®s->gtpsr2;
timers[1].gtcnr = ®s->gtcnr2;
timers[1].gtrfr = ®s->gtrfr2;
timers[1].gtevr = ®s->gtevr2;
timers[2].gtcfr = ®s->gtcfr2;
timers[2].gtmdr = ®s->gtmdr3;
- timers[2].gtpsr = ®s->gtpsr3;
timers[2].gtcnr = ®s->gtcnr3;
timers[2].gtrfr = ®s->gtrfr3;
timers[2].gtevr = ®s->gtevr3;
timers[3].gtcfr = ®s->gtcfr2;
timers[3].gtmdr = ®s->gtmdr4;
- timers[3].gtpsr = ®s->gtpsr4;
timers[3].gtcnr = ®s->gtcnr4;
timers[3].gtrfr = ®s->gtrfr4;
timers[3].gtevr = ®s->gtevr4;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
+ timers[0].gtpsr = ®s->gtpsr1;
+ timers[1].gtpsr = ®s->gtpsr2;
+ timers[2].gtpsr = ®s->gtpsr3;
+ timers[3].gtpsr = ®s->gtpsr4;
+ }
}
static int __init gtm_init(void)
@@ -307,7 +318,7 @@ static int __init gtm_init(void)
goto err;
}
- gtm_set_shortcuts(gtm->timers, gtm->regs);
+ gtm_set_shortcuts(np, gtm->timers, gtm->regs);
/* We don't want to lose the node and its ->data */
of_node_get(np);
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 15:07 ` Anton Vorontsov
@ 2008-04-17 16:14 ` Scott Wood
2008-04-17 16:43 ` Anton Vorontsov
0 siblings, 1 reply; 47+ messages in thread
From: Scott Wood @ 2008-04-17 16:14 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
Anton Vorontsov wrote:
> This isn't a timer with usec precision! This is a timer that silently
> crops precision as it wants to. Ahh, I see you dropped "u" prefix.
It is a timer with usec precision, unless you ask for a timeout of more
than 65535 usec -- at which point the hardware can't provide usec precision.
And s/as it wants to/as it needs to/.
> Well. I'm not going to use it anyway, so just give it some name you
> prefer and I'll wrap it into the patch. Preferably, drop a line here with
> kerneldoc for it, so I'll not have to document its drawbacks. :-)
/**
* gtm_reset_timer16 - reset 16 bit timer with arbitrary precision
* @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
* @usec: timer interval in microseconds
* @reload: if set, the timer will reset upon expiry rather than
* continue running free.
*
* This function (re)sets the GTM timer so that it counts up to the
* requested interval value, and fires the interrupt when the value is
* reached. This function will reduce the precision of the timer as
* needed in order for the requested timeout to fit in a 16-bit
* register.
*/
int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,
bool reload)
{
...
}
>> It could be made faster using cntlzw.
>
> No need to cntlzw, there is fls() already.
fls() uses cntlzw, does it not? I was just too lazy to look up what
Linux calls it. :-)
> Though, here you'll need two because of u64.
We can probably get away with 32 bits.
> Btw, I hope you aware that single GTM timer running at 166MHz will give you
> 6 minutes of sleep, maximum.
Yes, but it's all we have on-chip that can do the job.
> With cascaded timer you'll get much better
> result of 310 days. Is that possible to use cascaded timer as a wakeup
> event on 8313?
No, unfortunately. Only timer4 can be a wakeup source, and when
cascaded, timer4 is the input to timer3, rather than the other way around.
-Scott
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support
2008-04-17 16:14 ` Scott Wood
@ 2008-04-17 16:43 ` Anton Vorontsov
0 siblings, 0 replies; 47+ messages in thread
From: Anton Vorontsov @ 2008-04-17 16:43 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Thu, Apr 17, 2008 at 11:14:00AM -0500, Scott Wood wrote:
> Anton Vorontsov wrote:
>> This isn't a timer with usec precision! This is a timer that silently
>> crops precision as it wants to. Ahh, I see you dropped "u" prefix.
>
> It is a timer with usec precision, unless you ask for a timeout of more
> than 65535 usec -- at which point the hardware can't provide usec
> precision.
>
> And s/as it wants to/as it needs to/.
>
>> Well. I'm not going to use it anyway, so just give it some name you
>> prefer and I'll wrap it into the patch. Preferably, drop a line here with
>> kerneldoc for it, so I'll not have to document its drawbacks. :-)
>
> /**
> * gtm_reset_timer16 - reset 16 bit timer with arbitrary precision
> * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
> * @usec: timer interval in microseconds
> * @reload: if set, the timer will reset upon expiry rather than
> * continue running free.
> *
> * This function (re)sets the GTM timer so that it counts up to the
> * requested interval value, and fires the interrupt when the value is
> * reached. This function will reduce the precision of the timer as
> * needed in order for the requested timeout to fit in a 16-bit
> * register.
> */
> int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,
> bool reload)
> {
> ...
> }
Thanks!
>>> It could be made faster using cntlzw.
>>
>> No need to cntlzw, there is fls() already.
>
> fls() uses cntlzw, does it not? I was just too lazy to look up what
> Linux calls it. :-)
Yup, I looked it up. ;-)
>> Though, here you'll need two because of u64.
>
> We can probably get away with 32 bits.
>
>> Btw, I hope you aware that single GTM timer running at 166MHz will give you
>> 6 minutes of sleep, maximum.
>
> Yes, but it's all we have on-chip that can do the job.
>
>> With cascaded timer you'll get much better
>> result of 310 days. Is that possible to use cascaded timer as a wakeup
>> event on 8313?
>
> No, unfortunately. Only timer4 can be a wakeup source, and when
> cascaded, timer4 is the input to timer3, rather than the other way
> around.
Ok, very well.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2008-04-17 16:43 UTC | newest]
Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-11 17:21 [PATCH 0/8] A bit of new code and sparse cleanups along the way Anton Vorontsov
2008-03-11 17:23 ` [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines Anton Vorontsov
2008-04-11 14:06 ` Kumar Gala
2008-04-13 12:53 ` David Woodhouse
2008-04-14 15:10 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs Anton Vorontsov
2008-04-11 14:09 ` Kumar Gala
2008-04-11 16:13 ` Anton Vorontsov
2008-04-11 16:18 ` Scott Wood
2008-04-11 17:03 ` Anton Vorontsov
2008-04-12 4:09 ` Paul Mackerras
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset Anton Vorontsov
2008-03-18 17:48 ` Scott Wood
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h Anton Vorontsov
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 5/8] [POWERPC] qe_lib: export qe_get_brg_clk() Anton Vorontsov
2008-03-11 18:36 ` Kumar Gala
2008-03-11 18:44 ` Anton Vorontsov
2008-04-14 15:11 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 6/8] [POWERPC] sysdev,qe_lib: implement FSL GTM support Anton Vorontsov
2008-03-18 17:43 ` Scott Wood
2008-03-18 19:21 ` Anton Vorontsov
2008-03-18 19:55 ` Scott Wood
2008-03-18 20:27 ` Anton Vorontsov
2008-03-18 20:48 ` Scott Wood
2008-04-16 18:39 ` Anton Vorontsov
2008-04-16 18:44 ` Scott Wood
2008-04-16 21:00 ` Anton Vorontsov
2008-04-16 21:58 ` Scott Wood
2008-04-17 12:52 ` Anton Vorontsov
2008-04-17 14:19 ` Scott Wood
2008-04-17 15:07 ` Anton Vorontsov
2008-04-17 16:14 ` Scott Wood
2008-04-17 16:43 ` Anton Vorontsov
2008-04-17 14:23 ` Laurent Pinchart
2008-04-17 15:13 ` Anton Vorontsov
2008-04-17 16:12 ` Anton Vorontsov
2008-04-08 9:01 ` Laurent Pinchart
2008-04-08 11:48 ` Anton Vorontsov
2008-03-11 17:24 ` [PATCH 7/8] [POWERPC] qe_lib: add support for QE USB Anton Vorontsov
2008-04-14 20:29 ` Kumar Gala
2008-03-11 17:24 ` [PATCH 8/8] [POWERPC] qe_io: fix sparse warnings Anton Vorontsov
2008-04-14 15:12 ` Kumar Gala
2008-04-14 15:14 ` [PATCH 0/8] A bit of new code and sparse cleanups along the way Kumar Gala
2008-04-14 17:49 ` Anton Vorontsov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).