File indexing completed on 2025-05-11 08:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
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
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
0057
0058
0059 struct grpwm_pwm_regs {
0060 volatile unsigned int period;
0061 volatile unsigned int comp;
0062 volatile unsigned int dbcomp;
0063 volatile unsigned int ctrl;
0064 };
0065
0066
0067 struct grpwm_regs {
0068 volatile unsigned int ctrl;
0069 volatile unsigned int scaler;
0070 volatile unsigned int ipend;
0071 volatile unsigned int cap1;
0072 volatile unsigned int cap2;
0073 volatile unsigned int wctrl;
0074 int reserved0[2];
0075 struct grpwm_pwm_regs pwms[8];
0076 int reserved1[(0x8000-0xA0)/4];
0077 volatile unsigned int wram[0x8000/4];
0078 };
0079
0080
0081
0082
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
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
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
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
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
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
0177 char nscalers;
0178 char wave;
0179 int wlength;
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
0189 int irqindex;
0190 void (*isr)(int channel, void *arg);
0191 void *isr_arg;
0192 };
0193
0194
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}
0215 };
0216
0217 struct amba_drv_info grpwm_drv_info =
0218 {
0219 {
0220 DRVMGR_OBJ_DRV,
0221 NULL,
0222 NULL,
0223 DRIVER_AMBAPP_GAISLER_GRPWM_ID,
0224 "GRPWM_DRV",
0225 DRVMGR_BUS_TYPE_AMBAPP,
0226 &grpwm_ops,
0227 NULL,
0228 0,
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
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
0268 if ( grpwm_register_io(&grpwm_driver_io_major) ) {
0269
0270 dev->priv = NULL;
0271 return DRVMGR_FAIL;
0272 }
0273
0274 grpwm_driver_io_registered = 1;
0275 }
0276
0277
0278
0279
0280 if ( grpwm_device_init(priv) ) {
0281 free(dev->priv);
0282 dev->priv = NULL;
0283 return DRVMGR_FAIL;
0284 }
0285
0286
0287 prefix[0] = '\0';
0288 if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0289
0290
0291
0292 sprintf(priv->devName, "/dev/grpwm%d", dev->minor_drv);
0293 } else {
0294
0295
0296
0297 sprintf(priv->devName, "/dev/%sgrpwm%d", prefix, dev->minor_bus);
0298 }
0299
0300
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
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
0354 regs->ctrl = (regs->ctrl & ~GRPWM_CTRL_SCSEL) | (scaler << GRPWM_CTRL_SCSEL_BIT);
0355
0356 regs->scaler = value;
0357 }
0358
0359
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 = ®s->wram[0];
0369
0370
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
0391 regs->ctrl = 0;
0392
0393
0394 regs->ipend = 0xffffffff;
0395 regs->wctrl = 0;
0396
0397
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;
0405 }
0406
0407
0408 if ( priv->wave ) {
0409 grpwm_write_wram(regs, NULL, priv->wlength);
0410 }
0411
0412
0413 for (i=0; i<priv->nscalers; i++) {
0414 grpwm_scaler_set(regs, i, 0xffffffff);
0415 }
0416 }
0417
0418
0419
0420
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
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
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
0479 ctrl &= ~GRPWM_CTRL_NOUP;
0480
0481
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
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
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
0522 if ( !priv->wave || (priv->channel_cnt != (channel+1)) ) {
0523
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
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
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
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
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
0591 if ( rtems_semaphore_obtain(priv->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) !=
0592 RTEMS_SUCCESSFUL ){
0593 return RTEMS_INTERNAL_ERROR;
0594 }
0595
0596
0597 if ( priv->open ) {
0598 ret=RTEMS_RESOURCE_IN_USE;
0599 goto out;
0600 }
0601
0602
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
0622 grpwm_hw_reset(priv);
0623
0624
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:
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
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
0692 invalid_mask = ~((1 << priv->nscalers) - 1);
0693 if ( invalid_mask & sc->index_mask ) {
0694 return RTEMS_INVALID_NAME;
0695 }
0696
0697
0698 for (i=0; i<priv->nscalers; i++) {
0699 if ( sc->index_mask & (1<<i) ) {
0700
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
0716 invalid_mask = ~((1 << priv->channel_cnt) - 1);
0717 if ( invalid_mask & up->chanmask ) {
0718 return RTEMS_INVALID_NAME;
0719 }
0720
0721
0722
0723
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
0731 pctrl |= grpwm_update_prepare_channel(priv, i, &up->channels[i]);
0732 }
0733 }
0734
0735
0736
0737
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
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
0774 {0, 0, 0, 0, 0, 0, 0, 0},
0775 {0, 1, 0, 0, 0, 0, 0, 0},
0776 {0, 0, 0, 0, 0, 0, 0, 0},
0777 {0, 0, 0, 1, 0, 0, 0, 0},
0778 {0, 0, 0, 1, 2, 0, 0, 0},
0779 {0, 0, 0, 1, 1, 1, 0, 0},
0780 {0, 0, 0, 1, 1, 1, 2, 0},
0781 {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
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
0805 regs->ctrl = 0;
0806
0807
0808 regs->ipend = 0xffffffff;
0809 regs->wctrl = 0;
0810
0811
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
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 = ®s->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
0833 if ( regs->cap2 & GRPWM_CAP2_WPWM ) {
0834 priv->wave = 1;
0835
0836
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
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
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
0860
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 }