Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:07

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  GRPWM PWM Driver interface.
0005  *
0006  *  COPYRIGHT (c) 2009.
0007  *  Cobham Gaisler AB,
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 #include <bsp.h>
0032 #include <rtems/libio.h>
0033 #include <stdlib.h>
0034 #include <assert.h>
0035 #include <rtems/bspIo.h>
0036 #include <string.h>
0037 #include <stdio.h>
0038 
0039 #include <drvmgr/drvmgr.h>
0040 #include <grlib/ambapp_bus.h>
0041 #include <grlib/grpwm.h>
0042 #include <grlib/ambapp.h>
0043 
0044 #include <grlib/grlib_impl.h>
0045 
0046 /* #define DEBUG 1 */
0047 
0048 #ifdef DEBUG
0049 #define DBG(x...) printk(x)
0050 #define STATIC
0051 #else
0052 #define DBG(x...) 
0053 #define STATIC static
0054 #endif
0055 
0056 /*** REGISTER LAYOUT ***/
0057 
0058 /* PWM Channel specific registers */
0059 struct grpwm_pwm_regs {
0060     volatile unsigned int period;       /* 0x00 */
0061     volatile unsigned int comp;     /* 0x04 */
0062     volatile unsigned int dbcomp;       /* 0x08 */
0063     volatile unsigned int ctrl;     /* 0x0C */
0064 };
0065 
0066 /* Core common registers */ 
0067 struct grpwm_regs {
0068     volatile unsigned int ctrl;     /* 0x00 */
0069     volatile unsigned int scaler;       /* 0x04 */
0070     volatile unsigned int ipend;        /* 0x08 */
0071     volatile unsigned int cap1;     /* 0x0C */
0072     volatile unsigned int cap2;     /* 0x10 */
0073     volatile unsigned int wctrl;        /* 0x14 */
0074     int reserved0[2];
0075     struct grpwm_pwm_regs pwms[8];      /* 0x20 */
0076     int reserved1[(0x8000-0xA0)/4];     /* 0xA0-0x7FFC */
0077     volatile unsigned int wram[0x8000/4];   /* 0x8000-0xFFFC */
0078 };
0079 
0080 /*** REGISTER BIT LAYOUT ***/
0081 
0082 /* CTRL REGISTER - 0x0 */
0083 #define GRPWM_CTRL_EN_BIT   0
0084 #define GRPWM_CTRL_SCSEL_BIT    8
0085 #define GRPWM_CTRL_NOUP_BIT 12
0086 #define GRPWM_CTRL_EN       (1<<GRPWM_CTRL_EN_BIT)
0087 #define GRPWM_CTRL_SCSEL    (0x7<<GRPWM_CTRL_SCSEL_BIT)
0088 #define GRPWM_CTRL_NOUP     (0xff<<GRPWM_CTRL_NOUP_BIT)
0089 
0090 
0091 /* CAPABILITY1 REGISTER - 0x0C */
0092 #define GRPWM_CAP_NPWM_BIT  0
0093 #define GRPWM_CAP_PBITS_BIT 3
0094 #define GRPWM_CAP_SBITS_BIT 8
0095 #define GRPWM_CAP_NSC_BIT   13
0096 #define GRPWM_CAP_DBB_BIT   16
0097 #define GRPWM_CAP_DBSC_BIT  21
0098 #define GRPWM_CAP_ASY_BIT   22
0099 #define GRPWM_CAP_SYM_BIT   23
0100 #define GRPWM_CAP_SEP_BIT   25
0101 #define GRPWM_CAP_DCM_BIT   27
0102 
0103 #define GRPWM_CAP_NPWM  (0x7<<GRPWM_CAP_NPWM_BIT)
0104 #define GRPWM_CAP_PBITS (0x1f<<GRPWM_CAP_PBITS_BIT)
0105 #define GRPWM_CAP_SBITS (0x1f<<GRPWM_CAP_SBITS_BIT)
0106 #define GRPWM_CAP_NSC   (0x7<<GRPWM_CAP_NSC_BIT)
0107 #define GRPWM_CAP_DBB   (0x1f<<GRPWM_CAP_DBB_BIT)
0108 #define GRPWM_CAP_DBSC  (1<<GRPWM_CAP_DBSC_BIT)
0109 #define GRPWM_CAP_ASY   (1<<GRPWM_CAP_ASY_BIT)
0110 #define GRPWM_CAP_SYM   (1<<GRPWM_CAP_SYM_BIT)
0111 #define GRPWM_CAP_SEP   (0x3<<GRPWM_CAP_SEP_BIT)
0112 #define GRPWM_CAP_DCM   (1<<GRPWM_CAP_DCM_BIT)
0113 
0114 /* CAPABILITY2 REGISTER - 0x10 */
0115 #define GRPWM_CAP2_WPWM_BIT 0
0116 #define GRPWM_CAP2_WDBITS_BIT   1
0117 #define GRPWM_CAP2_WABITS_BIT   6
0118 #define GRPWM_CAP2_WSYNC_BIT    10
0119 
0120 #define GRPWM_CAP2_WPWM     (0x1<<GRPWM_CAP2_WPWM_BIT)
0121 #define GRPWM_CAP2_WDBITS   (0x1f<<GRPWM_CAP2_WDBITS_BIT)
0122 #define GRPWM_CAP2_WABITS   (0xf<<GRPWM_CAP2_WABITS_BIT)
0123 #define GRPWM_CAP2_WSYNC    (1<<GRPWM_CAP2_WSYNC_BIT)
0124 
0125 /* WAVE FORM CONFIG REGISTER - 0x14 */
0126 #define GRPWM_WCTRL_STOP_BIT        0
0127 #define GRPWM_WCTRL_WSYNC_BIT       16
0128 #define GRPWM_WCTRL_WSEN_BIT        29
0129 #define GRPWM_WCTRL_WSYNCCFG_BIT    30
0130 
0131 #define GRPWM_WCTRL_STOP    (0x1fff<<GRPWM_WCTRL_STOP_BIT)
0132 #define GRPWM_WCTRL_WSYNC   (0x1fff<<GRPWM_WCTRL_WSYNC_BIT)
0133 #define GRPWM_WCTRL_WSEN    (0x1<<GRPWM_WCTRL_WSEN_BIT)
0134 #define GRPWM_WCTRL_WSYNCCFG    (0x3<<GRPWM_WCTRL_WSYNCCFG_BIT)
0135 
0136 
0137 /* PWM CONTROL REGISTER - 0x2C, 0x3C... */
0138 #define GRPWM_PCTRL_EN_BIT  0
0139 #define GRPWM_PCTRL_POL_BIT 1
0140 #define GRPWM_PCTRL_PAIR_BIT    2
0141 #define GRPWM_PCTRL_FIX_BIT 3
0142 #define GRPWM_PCTRL_METH_BIT    6
0143 #define GRPWM_PCTRL_DCEN_BIT    8
0144 #define GRPWM_PCTRL_WEN_BIT 9
0145 #define GRPWM_PCTRL_SCSEL_BIT   10
0146 #define GRPWM_PCTRL_IEN_BIT 13
0147 #define GRPWM_PCTRL_IT_BIT  14
0148 #define GRPWM_PCTRL_ISC_BIT 15
0149 #define GRPWM_PCTRL_DBEN_BIT    21
0150 #define GRPWM_PCTRL_DBSC_BIT    22
0151 #define GRPWM_PCTRL_FLIP_BIT    26
0152 
0153 #define GRPWM_PCTRL_EN      (0x1<<GRPWM_PCTRL_EN_BIT)
0154 #define GRPWM_PCTRL_POL     (0x1<<GRPWM_PCTRL_POL_BIT)
0155 #define GRPWM_PCTRL_PAIR    (0x1<<GRPWM_PCTRL_PAIR_BIT)
0156 #define GRPWM_PCTRL_FIX     (0x7<<GRPWM_PCTRL_FIX_BIT)
0157 #define GRPWM_PCTRL_METH    (0x1<<GRPWM_PCTRL_METH_BIT)
0158 #define GRPWM_PCTRL_DCEN    (0x1<<GRPWM_PCTRL_DCEN_BIT)
0159 #define GRPWM_PCTRL_WEN     (0x1<<GRPWM_PCTRL_WEN_BIT)
0160 #define GRPWM_PCTRL_SCSEL   (0x7<<GRPWM_PCTRL_SCSEL_BIT)
0161 #define GRPWM_PCTRL_IEN     (0x1<<GRPWM_PCTRL_IEN_BIT)
0162 #define GRPWM_PCTRL_IT      (0x1<<GRPWM_PCTRL_IT_BIT)
0163 #define GRPWM_PCTRL_ISC     (0x3f<<GRPWM_PCTRL_ISC_BIT)
0164 #define GRPWM_PCTRL_DBEN    (0x1<<GRPWM_PCTRL_DBEN_BIT)
0165 #define GRPWM_PCTRL_DBSC    (0xf<<GRPWM_PCTRL_DBSC_BIT)
0166 #define GRPWM_PCTRL_FLIP    (0xf<<GRPWM_PCTRL_FLIP_BIT)
0167 
0168 /*** DRIVER PRIVATE STRUCTURE ***/
0169 struct grpwm_priv {
0170     struct drvmgr_dev   *dev;
0171     struct grpwm_regs       *regs;
0172     char                devName[52];
0173     int             irq;
0174     int             open;
0175 
0176     /* Driver implementation */
0177     char                nscalers;   /* Number of scalers */
0178     char                wave;       /* If Wave form is available */
0179     int             wlength;    /* Wave Form RAM Length */
0180     int             channel_cnt;
0181     struct grpwm_chan_priv      *channels[8];
0182     rtems_id            dev_sem;
0183 };
0184 
0185 struct grpwm_chan_priv {
0186     struct grpwm_priv       *common;
0187     struct grpwm_pwm_regs       *pwmregs;
0188     /* IRQ */
0189     int             irqindex;
0190     void                (*isr)(int channel, void *arg);
0191     void                *isr_arg;
0192 };
0193 
0194 /******************* Driver Manager Part ***********************/
0195 
0196 int grpwm_device_init(struct grpwm_priv *priv);
0197 int grpwm_register_io(rtems_device_major_number *m);
0198 static int grpwm_driver_io_registered = 0;
0199 static rtems_device_major_number grpwm_driver_io_major = 0;
0200 
0201 int grpwm_init2(struct drvmgr_dev *dev);
0202 int grpwm_init3(struct drvmgr_dev *dev);
0203 
0204 struct drvmgr_drv_ops grpwm_ops = 
0205 {
0206     .init = {NULL, grpwm_init2, grpwm_init3, NULL},
0207     .remove = NULL,
0208     .info = NULL
0209 };
0210 
0211 struct amba_dev_id grpwm_ids[] = 
0212 {
0213     {VENDOR_GAISLER, GAISLER_GRPWM},
0214     {0, 0}      /* Mark end of table */
0215 };
0216 
0217 struct amba_drv_info grpwm_drv_info =
0218 {
0219     {
0220         DRVMGR_OBJ_DRV,             /* Driver */
0221         NULL,                   /* Next driver */
0222         NULL,                   /* Device list */
0223         DRIVER_AMBAPP_GAISLER_GRPWM_ID,     /* Driver ID */
0224         "GRPWM_DRV",                /* Driver Name */
0225         DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
0226         &grpwm_ops,
0227         NULL,                   /* Funcs */
0228         0,                  /* No devices yet */
0229         0,
0230     },
0231     &grpwm_ids[0]
0232 };
0233 
0234 void grpwm_register_drv (void)
0235 {
0236     DBG("Registering GRPWM driver\n");
0237     drvmgr_drv_register(&grpwm_drv_info.general);
0238 }
0239 
0240 int grpwm_init2(struct drvmgr_dev *dev)
0241 {
0242     struct grpwm_priv *priv;
0243 
0244     DBG("GRPWM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0245 
0246     priv = dev->priv = grlib_malloc(sizeof(*priv));
0247     if ( !priv )
0248         return DRVMGR_NOMEM;
0249     memset(priv, 0, sizeof(*priv));
0250     priv->dev = dev;
0251 
0252     /* This core will not find other cores, so we wait for init2() */
0253 
0254     return DRVMGR_OK;
0255 }
0256 
0257 int grpwm_init3(struct drvmgr_dev *dev)
0258 {
0259     struct grpwm_priv *priv = dev->priv;
0260     char prefix[32];
0261     rtems_status_code status;
0262 
0263     if ( !priv )
0264         return DRVMGR_FAIL;
0265 
0266     if ( grpwm_driver_io_registered == 0) {
0267         /* Register the I/O driver only once for all cores */
0268         if ( grpwm_register_io(&grpwm_driver_io_major) ) {
0269             /* Failed to register I/O driver */
0270             dev->priv = NULL;
0271             return DRVMGR_FAIL;
0272         }
0273 
0274         grpwm_driver_io_registered = 1;
0275     }
0276 
0277     /* I/O system registered and initialized 
0278      * Now we take care of device initialization.
0279      */
0280     if ( grpwm_device_init(priv) ) {
0281         free(dev->priv);
0282         dev->priv = NULL;
0283         return DRVMGR_FAIL;
0284     }
0285 
0286     /* Get Filesystem name prefix */
0287     prefix[0] = '\0';
0288     if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0289         /* Failed to get prefix, make sure of a unique FS name
0290          * by using the driver minor.
0291          */
0292         sprintf(priv->devName, "/dev/grpwm%d", dev->minor_drv);
0293     } else {
0294         /* Got special prefix, this means we have a bus prefix
0295          * And we should use our "bus minor"
0296          */
0297         sprintf(priv->devName, "/dev/%sgrpwm%d", prefix, dev->minor_bus);
0298     }
0299 
0300     /* Register Device */
0301     status = rtems_io_register_name(priv->devName, grpwm_driver_io_major,
0302             dev->minor_drv);
0303     if (status != RTEMS_SUCCESSFUL) {
0304         return DRVMGR_FAIL;
0305     }
0306 
0307     return DRVMGR_OK;
0308 }
0309 
0310 /******************* Driver Implementation ***********************/
0311 
0312 static rtems_device_driver grpwm_initialize(rtems_device_major_number  major, rtems_device_minor_number  minor, void *arg);
0313 static rtems_device_driver grpwm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0314 static rtems_device_driver grpwm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0315 static rtems_device_driver grpwm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0316 static rtems_device_driver grpwm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0317 static rtems_device_driver grpwm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0318 
0319 #define GRPWM_DRIVER_TABLE_ENTRY { grpwm_initialize, grpwm_open, grpwm_close, grpwm_read, grpwm_write, grpwm_ioctl }
0320 
0321 static rtems_driver_address_table grpwm_driver = GRPWM_DRIVER_TABLE_ENTRY;
0322 
0323 int grpwm_register_io(rtems_device_major_number *m)
0324 {
0325     rtems_status_code r;
0326 
0327     if ((r = rtems_io_register_driver(0, &grpwm_driver, m)) == RTEMS_SUCCESSFUL) {
0328         DBG("GRPWM driver successfully registered, major: %d\n", *m);
0329     } else {
0330         switch(r) {
0331         case RTEMS_TOO_MANY:
0332             DBG("GRPWM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
0333             return -1;
0334         case RTEMS_INVALID_NUMBER:  
0335             DBG("GRPWM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
0336             return -1;
0337         case RTEMS_RESOURCE_IN_USE:
0338             DBG("GRPWM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
0339             return -1;
0340         default:
0341             DBG("GRPWM rtems_io_register_driver failed\n");
0342             return -1;
0343         }
0344     }
0345     return 0;
0346 }
0347 
0348 static void grpwm_scaler_set(
0349     struct grpwm_regs *regs,
0350     int scaler,
0351     unsigned int value)
0352 {
0353     /* Select scaler */
0354     regs->ctrl = (regs->ctrl & ~GRPWM_CTRL_SCSEL) | (scaler << GRPWM_CTRL_SCSEL_BIT);
0355     /* Write scaler */
0356     regs->scaler = value;
0357 }
0358 
0359 /* Write Wave form RAM */
0360 static void grpwm_write_wram(
0361     struct grpwm_regs *regs,
0362     unsigned int *data,
0363     int length)
0364 {
0365     unsigned int *end;
0366     volatile unsigned int *pos;
0367 
0368     pos = &regs->wram[0];
0369 
0370     /* Write RAM */
0371     if ( data ) {
0372         end = data + length;
0373         while ( data < end ) {
0374             *pos++ = *data++;
0375         }
0376     } else {
0377         while( length > 0 ) {
0378             *pos++ = 0;
0379             length -= 4;
0380         }
0381     }
0382 }
0383 
0384 static void grpwm_hw_reset(struct grpwm_priv *priv)
0385 {
0386     int i;
0387     struct grpwm_chan_priv *pwm;
0388     struct grpwm_regs *regs = priv->regs;
0389 
0390     /* Disable Core */
0391     regs->ctrl = 0;
0392 
0393     /* Clear all registers */
0394     regs->ipend = 0xffffffff;
0395     regs->wctrl = 0;
0396 
0397     /* Init all PWM channels */
0398     for (i=0; i<priv->channel_cnt; i++) {
0399         pwm = priv->channels[i];
0400         pwm->pwmregs->ctrl = 0;
0401         pwm->pwmregs->period = 0;
0402         pwm->pwmregs->comp = 0;
0403         pwm->pwmregs->dbcomp = 0;
0404         pwm->pwmregs->ctrl = 0; /* Twice because METH and POL requires EN=0 */
0405     }
0406 
0407     /* Clear RAM */
0408     if ( priv->wave ) {
0409         grpwm_write_wram(regs, NULL, priv->wlength);
0410     }
0411 
0412     /* Set max scaler */
0413     for (i=0; i<priv->nscalers; i++) {
0414         grpwm_scaler_set(regs, i, 0xffffffff);
0415     }
0416 }
0417 
0418 /* Update one Channel but leaves the "Hold update" bit set 
0419  *
0420  * A bit mask of updated bits are returned.
0421  */
0422 static unsigned int grpwm_update_prepare_channel(
0423     struct grpwm_priv *priv,
0424     int channel,
0425     struct grpwm_ioctl_update_chan *up
0426     )
0427 {
0428     struct grpwm_chan_priv *pwm;
0429     struct grpwm_pwm_regs *pwmregs;
0430     unsigned int ctrl;
0431     unsigned int ret;
0432 
0433     pwm = priv->channels[channel];
0434     pwmregs = pwm->pwmregs;
0435 
0436     /* Read channel control register */
0437     ctrl = pwmregs->ctrl;
0438     ret = 0;
0439 
0440     if ( up->options & GRPWM_UPDATE_OPTION_DISABLE ) {
0441         ctrl &= ~GRPWM_PCTRL_EN;
0442         pwmregs->ctrl = ctrl;
0443         ret |= GRPWM_PCTRL_EN;
0444     }
0445 
0446     /* Hold the updates */
0447     if ( up->options & (GRPWM_UPDATE_OPTION_PERIOD|
0448         GRPWM_UPDATE_OPTION_COMP|GRPWM_UPDATE_OPTION_DBCOMP) )  {
0449 
0450         if ( up->options & (GRPWM_UPDATE_OPTION_PERIOD) )  {
0451             DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->period, up->period);
0452             pwmregs->period = up->period;
0453         }
0454         if ( up->options & (GRPWM_UPDATE_OPTION_COMP) )  {
0455             DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->comp, up->compare);
0456             pwmregs->comp = up->compare;
0457         }
0458         if ( up->options & (GRPWM_UPDATE_OPTION_DBCOMP) )  {
0459             DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->dbcomp, up->dbcomp);
0460             pwmregs->dbcomp = up->dbcomp;
0461         }
0462     }
0463 
0464     if ( up->options & GRPWM_UPDATE_OPTION_ENABLE ) {
0465         ret |= GRPWM_PCTRL_EN;
0466         pwmregs->ctrl = ctrl | GRPWM_PCTRL_EN;
0467     }
0468     return ret;
0469 }
0470 
0471 static void grpwm_update_active(struct grpwm_priv *priv, int enable)
0472 {
0473     unsigned int ctrl;
0474     int i;
0475 
0476     ctrl = priv->regs->ctrl;
0477 
0478     /* Make all "Update Hold" bits be cleared */
0479     ctrl &= ~GRPWM_CTRL_NOUP;
0480 
0481     /* A change in any of the Channel enable/disable bits? */
0482     if ( enable ) {
0483         ctrl &= ~GRPWM_CTRL_EN;
0484         for(i=0; i<priv->channel_cnt; i++) {
0485             ctrl |= priv->regs->pwms[i].ctrl & GRPWM_CTRL_EN;
0486         }
0487     }
0488     priv->regs->ctrl = ctrl;
0489 }
0490 
0491 /* Configure the hardware of a channel according to this */
0492 static rtems_status_code grpwm_config_channel(
0493     struct grpwm_priv *priv,
0494     int channel,
0495     struct grpwm_ioctl_config *cfg
0496     )
0497 {
0498     struct grpwm_chan_priv *pwm;
0499     unsigned int pctrl, wctrl=0;
0500 
0501     pwm = priv->channels[channel];
0502     if ( pwm->pwmregs->ctrl & GRPWM_PCTRL_EN ) {
0503         return RTEMS_RESOURCE_IN_USE;
0504     }
0505     if ( cfg->options & ~GRPWM_CONFIG_OPTION_MASK ) {
0506         return RTEMS_INVALID_NAME;
0507     }
0508     if ( (cfg->options & GRPWM_CONFIG_OPTION_DUAL) && 
0509          ((priv->regs->cap1 & GRPWM_CAP_DCM) == 0) ) {
0510         return RTEMS_INVALID_NAME;
0511     }
0512     /* IRQ set up */
0513     pwm->isr_arg = cfg->isr_arg;
0514     pwm->isr = cfg->isr;
0515 
0516     pctrl = cfg->options |
0517         (cfg->dbscaler << GRPWM_PCTRL_DBSC_BIT) |
0518         (cfg->irqscaler << GRPWM_PCTRL_ISC_BIT) |
0519         (cfg->scaler_index << GRPWM_PCTRL_SCSEL_BIT);
0520 
0521     /* Set Wave form gerneration if available */
0522     if ( !priv->wave || (priv->channel_cnt != (channel+1)) ) {
0523         /* Wave Form not available for this channel (or core) */
0524         if ( cfg->wave_activate || cfg->wave_data || cfg->wave_data_length ) {
0525             return RTEMS_INVALID_NAME;
0526         }
0527     } else if ( cfg->wave_activate ) {
0528         /* Enable Wave form generation */
0529         DBG("GRPWM: ENABLING WAVE FORM GENERATION 0x%x\n", cfg->wave_data_length);
0530 
0531         if ( cfg->wave_data ) {
0532             grpwm_write_wram(priv->regs, cfg->wave_data, cfg->wave_data_length);
0533         }
0534 
0535         /* Write length register, and let user control Wave-Sync functionality */
0536         wctrl = (((cfg->wave_data_length-1) << GRPWM_WCTRL_STOP_BIT) & GRPWM_WCTRL_STOP);
0537         wctrl |= cfg->wave_synccfg & (GRPWM_WCTRL_WSYNCCFG|GRPWM_WCTRL_WSEN);
0538         wctrl |= (cfg->wave_sync << 16) & 0x1fff0000;
0539         priv->regs->wctrl = wctrl;
0540 
0541         /* Enable Wave form */
0542         pctrl |= GRPWM_PCTRL_WEN;
0543     }
0544 
0545     DBG("GRPWM: CONFIG: 0x%x, WAVE CONFIG: 0x%x\n", pctrl, wctrl);
0546 
0547     pwm->pwmregs->ctrl = pctrl;
0548 
0549     return RTEMS_SUCCESSFUL;
0550 }
0551 
0552 static void grpwm_isr(void *arg)
0553 {
0554     unsigned int ipend;
0555     struct grpwm_chan_priv *pwm = arg;
0556     struct grpwm_priv *priv = pwm->common;
0557     int i;
0558 
0559     /* Get current pending interrupts */
0560     ipend = priv->regs->ipend;
0561 
0562     for (i=0; i<priv->channel_cnt; i++) {
0563         if ( ipend & (1<<i) ) {
0564             pwm = priv->channels[i];
0565             if ( pwm->isr ) {
0566                 pwm->isr(i, pwm->isr_arg);
0567             }
0568         }
0569     }
0570     priv->regs->ipend = ipend;
0571 }
0572 
0573 static rtems_device_driver grpwm_initialize(rtems_device_major_number  major, rtems_device_minor_number  minor, void *arg)
0574 {
0575     return RTEMS_SUCCESSFUL;
0576 }
0577 
0578 static rtems_device_driver grpwm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0579 {
0580     struct grpwm_priv *priv;
0581     rtems_device_driver ret;
0582     struct drvmgr_dev *dev;
0583 
0584     if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) {
0585         DBG("Wrong minor %d\n", minor);
0586         return RTEMS_INVALID_NAME;
0587     }
0588     priv = (struct grpwm_priv *)dev->priv;
0589 
0590     /* Wait until we get semaphore */
0591     if ( rtems_semaphore_obtain(priv->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) !=
0592          RTEMS_SUCCESSFUL ){
0593         return RTEMS_INTERNAL_ERROR;
0594     }
0595 
0596     /* is device busy/taken? */
0597     if  ( priv->open ) {
0598         ret=RTEMS_RESOURCE_IN_USE;
0599         goto out;
0600     }
0601 
0602     /* Mark device taken */
0603     priv->open = 1;
0604 
0605     ret = RTEMS_SUCCESSFUL;
0606 out:
0607     rtems_semaphore_release(priv->dev_sem);
0608     return ret;
0609 }
0610 
0611 static rtems_device_driver grpwm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0612 {
0613     struct grpwm_priv *priv;
0614     struct drvmgr_dev *dev;
0615 
0616     if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) {
0617         return RTEMS_INVALID_NAME;
0618     }
0619     priv = (struct grpwm_priv *)dev->priv;
0620 
0621     /* Reset Hardware */
0622     grpwm_hw_reset(priv);
0623 
0624     /* Mark Device closed */
0625     priv->open = 0;
0626 
0627     return RTEMS_SUCCESSFUL;
0628 }
0629 
0630 static rtems_device_driver grpwm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0631 {
0632     return RTEMS_UNSATISFIED;
0633 }
0634 
0635 static rtems_device_driver grpwm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0636 {
0637     return RTEMS_UNSATISFIED;
0638 }
0639 
0640 static rtems_device_driver grpwm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0641 {
0642 
0643     struct grpwm_priv *priv;
0644     struct drvmgr_dev *dev;
0645     rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
0646 
0647     if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) {
0648         return RTEMS_INVALID_NAME;
0649     }
0650     priv = (struct grpwm_priv *)dev->priv;
0651 
0652     if (!ioarg)
0653         return RTEMS_INVALID_NAME;
0654 
0655     ioarg->ioctl_return = 0;
0656     switch(ioarg->command) {
0657         default: /* Not a valid command */
0658             return RTEMS_NOT_DEFINED;
0659 
0660         case GRPWM_IOCTL_GET_CAP:
0661         {
0662             struct grpwm_ioctl_cap *cap = (void *)ioarg->buffer;
0663             if ( cap == NULL )
0664                 return RTEMS_INVALID_NAME;
0665 
0666             /* Copy Capability registers to user */
0667             cap->channel_cnt = priv->channel_cnt;
0668             cap->pwm = priv->regs->cap1;
0669             cap->wave = priv->regs->cap2;
0670             break;
0671         }
0672         case GRPWM_IOCTL_SET_CONFIG:
0673         {
0674             struct grpwm_ioctl_config *cfg = (void *)ioarg->buffer;
0675             if ( cfg == NULL )
0676                 return RTEMS_INVALID_NAME;
0677             if ( cfg->channel >= priv->channel_cnt )
0678                 return RTEMS_INVALID_NAME;
0679 
0680             return grpwm_config_channel(priv, cfg->channel, cfg);
0681         }
0682         case GRPWM_IOCTL_SET_SCALER:
0683         {
0684             unsigned int invalid_mask;
0685             int i;
0686             struct grpwm_ioctl_scaler *sc = ioarg->buffer;
0687 
0688             if ( sc == NULL )
0689                 return RTEMS_INVALID_NAME;
0690 
0691             /* Test if caller reqest to set a scaler not existing */
0692             invalid_mask = ~((1 << priv->nscalers) - 1);
0693             if ( invalid_mask & sc->index_mask ) {
0694                 return RTEMS_INVALID_NAME;
0695             }
0696 
0697             /* Set scalers requested */
0698             for (i=0; i<priv->nscalers; i++) {
0699                 if ( sc->index_mask & (1<<i) ) {
0700                     /* Update Scaler 'i' */
0701                     grpwm_scaler_set(priv->regs, i, sc->values[i]);
0702                 }
0703             }
0704             break;
0705         }
0706         case GRPWM_IOCTL_UPDATE:
0707         {
0708             struct grpwm_ioctl_update *up = ioarg->buffer;
0709             unsigned int invalid_mask, pctrl = 0;
0710             int i;
0711 
0712             if ( up == NULL )
0713                 return RTEMS_INVALID_NAME;
0714 
0715             /* Test if caller reqest to set a scaler not existing */
0716             invalid_mask = ~((1 << priv->channel_cnt) - 1);
0717             if ( invalid_mask & up->chanmask ) {
0718                 return RTEMS_INVALID_NAME;
0719             }
0720 
0721             /* In order for the changes to take effect at the same time, the "Hold update"
0722              * bits is set for all PWM channels that will be updated. The hold update bits
0723              * will be cleared at the same time for all channels.
0724              */
0725             priv->regs->ctrl = (priv->regs->ctrl & ~GRPWM_CTRL_NOUP) | 
0726                 (up->chanmask << GRPWM_CTRL_NOUP_BIT);
0727 
0728             for (i=0; i<priv->channel_cnt; i++) {
0729                 if ( up->chanmask & (1<<i) ) {
0730                     /* Prepare update channel 'i' */
0731                     pctrl |= grpwm_update_prepare_channel(priv, i, &up->channels[i]);
0732                 }
0733             }
0734 
0735             /* 1. Update all channels requested, 
0736              * 2. Enable the core if at least one channel is enabled
0737              * 3. Disable the core if all channels are disabled
0738              */
0739             grpwm_update_active(priv, (pctrl & GRPWM_PCTRL_EN));
0740 
0741             break;
0742         }
0743         case GRPWM_IOCTL_IRQ:
0744         {
0745             unsigned int data = (unsigned int)ioarg->buffer;
0746             int channel = (data >> 8) & 0x7;
0747             struct grpwm_chan_priv *pwm;
0748             unsigned int pctrl;
0749 
0750             pwm = priv->channels[channel];
0751 
0752             if ( data & GRPWM_IRQ_CLEAR ) {
0753                 priv->regs->ipend |= (1<<channel);
0754                 drvmgr_interrupt_clear(priv->dev, pwm->irqindex);
0755             }
0756             if ( (data & 0x3) && !pwm->isr ) {
0757                 /* Enable IRQ but no ISR */
0758                 return RTEMS_INVALID_NAME;
0759             }
0760             pctrl = pwm->pwmregs->ctrl & ~(GRPWM_PCTRL_IEN|GRPWM_PCTRL_IT);
0761             pctrl |= ((data & 0x3) << GRPWM_PCTRL_IEN_BIT);
0762             pwm->pwmregs->ctrl = pctrl;
0763             break;
0764         }
0765     }
0766 
0767     return RTEMS_SUCCESSFUL;
0768 }
0769 
0770 #define MAX_CHANNEL 8
0771 char grpwm_irqindex_lookup[8][MAX_CHANNEL] = 
0772 {
0773 /* Channel       1  2  3  4  5  6  7  8 */
0774 /* npwm 1 */    {0, 0, 0, 0, 0, 0, 0, 0},
0775 /* npwm 2 */    {0, 1, 0, 0, 0, 0, 0, 0},
0776 /* npwm 3 */    {0, 0, 0, 0, 0, 0, 0, 0},
0777 /* npwm 4 */    {0, 0, 0, 1, 0, 0, 0, 0},
0778 /* npwm 5 */    {0, 0, 0, 1, 2, 0, 0, 0},
0779 /* npwm 6 */    {0, 0, 0, 1, 1, 1, 0, 0},
0780 /* npwm 7 */    {0, 0, 0, 1, 1, 1, 2, 0},
0781 /* npwm 8 */    {0, 0, 0, 1, 1, 1, 2, 3}
0782 };
0783 
0784 int grpwm_device_init(struct grpwm_priv *priv)
0785 {
0786     struct amba_dev_info *ambadev;
0787     struct ambapp_core *pnpinfo;
0788     int mask, i, sepirq;
0789     unsigned int wabits;
0790     struct grpwm_chan_priv *pwm;
0791     struct grpwm_regs *regs;
0792 
0793     /* Get device information from AMBA PnP information */
0794     ambadev = (struct amba_dev_info *)priv->dev->businfo;
0795     if ( ambadev == NULL ) {
0796         return -1;
0797     }
0798     pnpinfo = &ambadev->info;
0799     priv->irq = pnpinfo->irq;
0800     regs = priv->regs = (struct grpwm_regs *)pnpinfo->apb_slv->start;
0801 
0802     DBG("GRPWM: 0x%08x irq %d\n", (unsigned int)regs, priv->irq);
0803 
0804     /* Disable Core */
0805     regs->ctrl = 0;
0806 
0807     /* Clear all registers */
0808     regs->ipend = 0xffffffff;
0809     regs->wctrl = 0;
0810 
0811     /* Find the number of PWM channels */
0812     priv->channel_cnt = 1 + ((regs->cap1 & GRPWM_CAP_NPWM) >> GRPWM_CAP_NPWM_BIT);
0813     pwm = grlib_calloc(priv->channel_cnt, sizeof(*pwm));
0814     if ( !pwm )
0815         return -1;
0816 
0817     /* Init all PWM channels */
0818     sepirq = ((regs->cap1 & GRPWM_CAP_SEP) >> GRPWM_CAP_SEP_BIT);
0819     for (i=0; i<priv->channel_cnt; i++, pwm++) {
0820         priv->channels[i] = pwm;
0821         pwm->common = priv;
0822         pwm->pwmregs = &regs->pwms[i];
0823         if ( sepirq == 0 ) {
0824             pwm->irqindex = 0;
0825         } else if ( sepirq == 1 ) {
0826             pwm->irqindex = i;
0827         } else {
0828             pwm->irqindex = grpwm_irqindex_lookup[priv->channel_cnt][i];
0829         }
0830     }
0831 
0832     /* Detect if Wave Form capability is availble for last PWM channel */
0833     if ( regs->cap2 & GRPWM_CAP2_WPWM ) {
0834         priv->wave = 1;
0835 
0836         /* Clear RAM */
0837         wabits = (regs->cap2 & GRPWM_CAP2_WABITS) >> GRPWM_CAP2_WABITS_BIT;
0838         priv->wlength = 1 << wabits;
0839     }
0840     priv->nscalers = 1 + ((regs->cap1 & GRPWM_CAP_NSC) >> GRPWM_CAP_NSC_BIT);
0841 
0842     grpwm_hw_reset(priv);
0843 
0844     /* Device Semaphore created with count = 1 */
0845     if ( rtems_semaphore_create(rtems_build_name('G', 'P', 'W', 'M'),
0846         1,
0847         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0848         RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
0849         0,
0850         &priv->dev_sem) != RTEMS_SUCCESSFUL ) {
0851         return -1;
0852     }
0853 
0854     /* Register interrupt handler for all PWM channels */
0855     mask = 0;
0856     for (i=0; i<priv->channel_cnt; i++) {
0857         pwm = priv->channels[i];
0858         if ( (mask & (1 << pwm->irqindex)) == 0 ) {
0859             /* Not registered interrupt handler for this IRQ index before,
0860              * we do it now.
0861              */
0862             mask |= (1 << pwm->irqindex);
0863             drvmgr_interrupt_register(
0864                 priv->dev,
0865                 pwm->irqindex,
0866                 "grpwm",
0867                 grpwm_isr,
0868                 pwm);
0869         }
0870     }
0871 
0872     return 0;
0873 }