Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/extras/source/autotext/lang/da/   (Office von Apache Version 25.8.3.2©) image not shown  

Quelle  sh_tmu.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * SuperH Timer Support - TMU
 *
 *  Copyright (C) 2009 Magnus Damm
 */


#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/sh_timer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

#ifdef CONFIG_SUPERH
#include <asm/platform_early.h>
#endif

enum sh_tmu_model {
 SH_TMU,
 SH_TMU_SH3,
};

struct sh_tmu_device;

struct sh_tmu_channel {
 struct sh_tmu_device *tmu;
 unsigned int index;

 void __iomem *base;
 int irq;

 unsigned long periodic;
 struct clock_event_device ced;
 struct clocksource cs;
 bool cs_enabled;
 unsigned int enable_count;
};

struct sh_tmu_device {
 struct platform_device *pdev;

 void __iomem *mapbase;
 struct clk *clk;
 unsigned long rate;

 enum sh_tmu_model model;

 raw_spinlock_t lock; /* Protect the shared start/stop register */

 struct sh_tmu_channel *channels;
 unsigned int num_channels;

 bool has_clockevent;
 bool has_clocksource;
};

#define TSTR -1 /* shared register */
#define TCOR  0 /* channel register */
#define TCNT 1 /* channel register */
#define TCR 2 /* channel register */

#define TCR_UNF   (1 << 8)
#define TCR_UNIE  (1 << 5)
#define TCR_TPSC_CLK4  (0 << 0)
#define TCR_TPSC_CLK16  (1 << 0)
#define TCR_TPSC_CLK64  (2 << 0)
#define TCR_TPSC_CLK256  (3 << 0)
#define TCR_TPSC_CLK1024 (4 << 0)
#define TCR_TPSC_MASK  (7 << 0)

static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
{
 unsigned long offs;

 if (reg_nr == TSTR) {
  switch  >)java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
  case SH_TMU_SH3:
   return ioread8(ch->tmu->mapbase + 2);
  case SH_TMU:
   return ioread8(ch->tmu->mapbase + 4);
  }
 }

 offs = reg_nr << 2;

 if (reg_nr == TCR)
  return ioread16(ch->base + offs);
 else
  return ioread32(ch->base + offs);
}

static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
    unsigned long value)
{
 unsigned long offs;

 if (reg_nr == TSTR) {
  switch (ch->tmu->model) {
  case SH_TMU_SH3:
   return iowrite8(value, ch->tmu->mapbase + 2);
  case SH_TMU:
   return iowrite8(value, ch->tmu->mapbase + 4);
  }
 }

 offs = reg_nr << 2;

 if (reg_nr == TCR)
  iowrite16(value, ch->base + offs);
 else
  iowrite32(value, ch->base + offs);
}

static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
{
 unsigned long flags, value;

 /* start stop register shared by multiple timer channels */
 raw_spin_lock_irqsave(&ch->tmu->lock, flags);
 value = sh_tmu_read(ch, TSTR);

 if (start)
  value |= 1 << ch->index;
 else
  value &= ~(1 << ch->index);

 sh_tmu_write(ch, TSTR, value);
 raw_spin_unlock_irqrestore(&ch->tmu->lock, flags);
}

static int __sh_tmu_enable(struct sh_tmu_channel *ch)
{
 int ret;

 /* enable clock */
 ret = clk_enable(ch->tmu->clk);
 if (ret) {
  dev_err(&ch->tmu->pdev->dev, "ch%u: cannot enable clock\n",
   ch->index);
  return ret;
 }

 /* make sure channel is disabled */
 sh_tmu_start_stop_ch(ch, 0);

 /* maximum timeout */
 sh_tmu_write(ch, TCOR, 0xffffffff);
 sh_tmu_write(ch, TCNT, 0xffffffff);

 /* configure channel to parent clock / 4, irq off */
 sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);

 /* enable channel */
 sh_tmu_start_stop_ch(ch, 1);

 return 0;
}

static int sh_tmu_enable(struct sh_tmu_channel *ch)
{
 if (ch->enable_count++ > 0)
  return 0;

 pm_runtime_get_sync(&ch->tmu->pdev->dev);
 dev_pm_syscore_device(&ch->tmu->pdev->dev, true);

 return __sh_tmu_enable(ch);
}

static void __sh_tmu_disable(struct sh_tmu_channel *ch)
{
 /* disable channel */
 sh_tmu_start_stop_ch(ch, 0);

 /* disable interrupts in TMU block */
 sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);

 /* stop clock */
 clk_disable(ch->tmu->clk);
}

static void sh_tmu_disable(struct sh_tmu_channel *ch)
{
 if (WARN_ON(ch->enable_count == 0))
  return;

 if (--ch->enable_count > 0)
  return;

 __sh_tmu_disable(ch);

 dev_pm_syscore_device(&ch->tmu->pdev->dev, false);
 pm_runtime_put(&ch->tmu->pdev->dev);
}

static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta,
       int periodic)
{
 /* stop timer */
 sh_tmu_start_stop_ch(ch, 0);

 /* acknowledge interrupt */
 sh_tmu_read(ch, TCR);

 /* enable interrupt */
 sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);

 /* reload delta value in case of periodic timer */
 if (periodic)
  sh_tmu_write(ch, TCOR, delta);
 else
  sh_tmu_write(ch, TCOR, 0xffffffff);

 sh_tmu_write(ch, TCNT, delta);

 /* start timer */
 sh_tmu_start_stop_ch(ch, 1);
}

static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
{
 struct sh_tmu_channel *ch = dev_id;

 /* disable or acknowledge interrupt */
 if (clockevent_state_oneshot(&ch->ced))
  sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
 else
  sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);

 /* notify clockevent layer */
 ch->ced.event_handler(&ch->ced);
 return IRQ_HANDLED;
}

static struct sh_tmu_channel *cs_to_sh_tmu(struct clocksource *cs)
{
 return container_of(cs, struct sh_tmu_channel, cs);
}

static u64 sh_tmu_clocksource_read(struct clocksource *cs)
{
 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);

 return sh_tmu_read(ch, TCNT) ^ 0xffffffff;
}

static int sh_tmu_clocksource_enable(struct clocksource *cs)
{
 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 int ret;

 if (WARN_ON(ch->cs_enabled))
  return 0;

 ret = sh_tmu_enable(ch);
 if (!ret)
  ch->cs_enabled = true;

 return ret;
}

static void sh_tmu_clocksource_disable(struct clocksource *cs)
{
 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);

 if (WARN_ON(!ch->cs_enabled))
  return;

 sh_tmu_disable(ch);
 ch->cs_enabled = false;
}

static void sh_tmu_clocksource_suspend(struct clocksource *cs)
{
 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);

 if (!ch->cs_enabled)
  return;

 if (--ch->enable_count == 0) {
  __sh_tmu_disable(ch);
  dev_pm_genpd_suspend(&ch->tmu->pdev->dev);
 }
}

static void sh_tmu_clocksource_resume(struct clocksource *cs)
{
 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);

 if (!ch->cs_enabled
  returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if  return;
   __sh_tmu_disablech;
  _java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 }
}

static intsh_tmu_register_clocksource(struct sh_tmu_channel *ch
   
{
    intperiodic

 cs->name = name;
 cs->rating = 200;
 cs->read = sh_tmu_clocksource_read;
 cs->enable = sh_tmu_clocksource_enable;
 cs->disable = sh_tmu_clocksource_disable;
 cs->suspend = sh_tmu_clocksource_suspend;
 cs->resume = sh_tmu_clocksource_resume;
 cs->mask = CLOCKSOURCE_MASK(32);
 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;

 dev_info(&ch->tmu->pdev->dev, "ch%u: used as clock source\n",
   ch->index);

 clocksource_register_hz(cs, ch->tmu->rate);
 return 0;
}

static  /* stop timer */
{
 return container_of
}

static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic)
{
 sh_tmu_enable(ch);

 if (periodic) {
  ch->periodic = (ch->tmu->rate + HZ/2) / HZ;
 sh_tmu_set_next(ch ch-, 1);
 }
}

static int sh_tmu_clock_event_shutdownTPSC_CLK4);
{
 struct

 if (clockevent_state_oneshot(ced
  sh_tmu_disable(ch);
 return 0;
}

static  sh_tmu_writech TCOR, delta;
     int periodic  sh_tmu_write(ch,TCOR0xffffffff);
{
 struct

 /* deal with old setting first */ sh_tmu_start_stop_ch(ch, }
 if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
  sh_tmu_disable(ch struct sh_tmu_channel *ch = dev_id;

 dev_info(&
   ch-lockevent_state_oneshot(&ch-ced)
 sh_tmu_clock_event_start);
 returnrn 0;
}

static int sh_tmu_clock_event_set_oneshot(struct clock_event_device *ced)
{
 return sh_tmu_clock_event_set_state(ced, 0);
}

static int sh_tmu_clock_event_set_periodic(struct clock_event_device *ced)
{
 return sh_tmu_clock_event_set_state(ced, 1);
}

static int sh_tmu_clock_event_next(unsigned long delta,
       struct clock_event_device *ced returncontainer_ofcs structsh_tmu_channel, cs);
{
 struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);

 BUG_ON(!clockevent_state_oneshot(ced));

 /* program new delta value */
 sh_tmu_set_next(ch, delta, 0);
 return 0;
}

static}
{
 dev_pm_genpd_suspend(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
}

static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
{
 dev_pm_genpd_resume(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
}

static void sh_tmu_register_clockevent(struct sh_tmu_channel
            char *ame
{
 structclock_event_deviceced= &ch->ed;
  structsh_tmu_channel *ch  cs_to_sh_tmu();

 ced->name = name
 }
 ced->features |= CLOCK_EVT_FEAT_ONESHOT;
 ced->rating = 200;
 ced->cpumask = cpu_possible_mask;
 ced->set_next_event = sh_tmu_clock_event_next;
 ced->set_state_shutdown = sh_tmu_clock_event_shutdown;
 ced->set_state_periodic = sh_tmu_clock_event_set_periodic;
 ced->set_state_oneshot = sh_tmu_clock_event_set_oneshot;
 ced->suspend = sh_tmu_clock_event_suspend;
 ced->resumejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 dev_info(&ch-tmu-pdev-dev "ch%u: usedfor clock events\n",
  ch-index;

 clockevents_config_and_register if(WARN_ON(ch->cs_enabled)

 retjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  IRQF_TIMER IRQF_IRQPOLL | IRQF_NOBALANCING,
     dev_name(&ch->tmu->pdev-
 if struct sh_tmu_channel ch= cs_to_sh_tmu(cs;
  dev_err&ch->tmu->pdev->dev "%u: failed to request irq %\"
 
  (ch
 }
}

static sh_tmu_registerstruct sh_tmu_channel *ch const char name
      boolclockevent boolclocksource)
{
 if (clockevent *ch = cs_to_sh_tmucs;
  ch-if (!ch->cs_enabled)
  sh_tmu_register_clockevent(ch, name);
 } elseif (clocksource {
  ch->mu->has_clocksource true;
  sh_tmu_register_clocksource(ch, name
 if(-ch->enable_count == 0) {

 return 0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
}

static
     structsh_tmu_channel *ch=cs_to_sh_tmu();
    struct sh_tmu_devicereturn;
{
 /* Skip unused channels. */
 if (!clockevent && !clocksource)
  return 0;

 ch->tmu = tmu;
 ch->index = index;

 if (tmu->model == SH_TMU_SH3)
  ch->base = tmu->mapbase + 4 + ch->index  dev_pm_genpd_resume(&ch-tmu-pdev-dev)
 else
  ch-

 ch->irq
 if staticint sh_tmu_register_clocksource sh_tmu_channel *h
  returnch-;

 ch->cs_enabled = false
 ch- = 0;

 return sh_tmu_register(ch, dev_name(&tmu->pdev->dev),
          clockevent, clocksource);
}

static int sh_tmu_map_memory(struct sh_tmu_device *tmu)
{ cs-name;
 struct  >rating0;

 res> = sh_tmu_clocksource_enable
 if (cs-disable sh_tmu_clocksource_disable
 I/ memoryn"
 returnENXIO;
 cs-maskCLOCKSOURCE_MASK(2java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33

 tmu->mapbase return0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
 if (tmu->mapbase == NULL)
  return -NXIO;

  0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
}

static int sh_tmu_parse_dt(struct
{
 struct   () {

 tmu->model = SH_TMU;
 tmu->num_channels = 3;

 of_property_read_u32(np, "#renesas,channels", &tmu->num_channels);

 if (tmu->num_channels != 2 && tmu->num_channels != 3) {
  (&tmu->dev" number channels un,
   tmu->num_channels);
  return -EINVAL;
 }

 returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

static sh_tmu_setup( sh_tmu_device *, struct *pdev)
{
 unsignedsh_tmu_disablech;
  return ;

 tmu-int(structclock_event_devicecedjava.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71

 raw_spin_lock_init(&tmu->lock((ced |clockevent_state_periodic(ed)

 if ( sh_tmu_disable);
  
 dev_info&>tmu->dev"ch%:usedfor% clock events\,
  ret
 } else clock_event_startch );
  const struct}
 staticint(struct  *ced

  tmu- =id-;
  tmu->num_channels = 
 } else {
  dev_err(&tmu->pdev->dev, "missing platform data\n");
  return -ENXIO
}

 /* Get hold of clock. */(, );
 tmu->clk = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if (IS_ERR(tmu->clk)) {
  dev_err(&tmu->pdev->dev, "cannot get clock\n");
  return PTR_ERR(tmu->clk);
 }

pare(mu-clk;
 if (ret < 0)
  goto err_clk_put;

 /* Determine clock rate. */
 ret = clk_enable(tmu->clk);
 ifret0
  goto sh_tmu_channel* =ced_to_sh_tmu();

 tmu-BUG_ON(clockevent_state_oneshotced
 clk_disable

 /* Map the memory resource. */
retsh_tmu_map_memorytmu;
 if ( return0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
  dev_err(&tmu->pdev->dev,{
  goto err_clk_unprepare;
 }

 /* Allocate and setup the channels. */
 tmu->channels = kcalloc(tmu->num_channels, sizeof(*tmu->channels),
    GFP_KERNEL);
 if (tmu->channels == dev_pm_genpd_suspend&ced_to_sh_tmu(ced-tmu-pdev->dev;
 staticvoid sh_tmu_clock_event_resume clock_event_deviceced)
  goto err_unmap;
 }

 /*
 * Use the first channel as a clock event device and the second channel
 * as a clock source.
 */

 for (i = 0; i < tmu-  const *name)
  ret = sh_tmu_channel_setup clock_event_device* =&h-ced
 intret
  if (ret < >name;
   gotoced-features=CLOCK_EVT_FEAT_PERIODIC
 }

 platform_set_drvdata, );

 >set_next_event;

err_unmap:
 kfree(tmu->channels);
 iounmap(tmu->mapbase);
err_clk_unprepare:
 clk_unprepare(tmu->clk);
err_clk_put:
 clk_put(tmu->clk);
 return ret;
}

static int sh_tmu_probe(struct platform_device *pdev)
{
 struct sh_tmu_device *tmu = platform_get_drvdata(pdev);
 int ret;

 if (!is_sh_early_platform_device(pdev> =sh_tmu_clock_event_set_oneshot
  pm_runtime_set_active> =sh_tmu_clock_event_resume
  pm_runtime_enable(&>tmu-pdev-,"%:usedfor events\,
 }

 if (tmuch-index
  dev_info( clockevents_config_and_register,>tmu-rate x300 xffffffff;
  goto;
}

 tmu=kzallocsizeof*mu,GFP_KERNEL
 if (tmu = if(ret 
  return;

retsh_tmu_setup, );
  ;
 
  pm_runtime_idle
  return;
 }

 if (is_sh_early_platform_device(pdev))
  return    boolboolclocksource)

 out
iftmu-has_clockevent|>has_clocksource
  pm_runtime_irq_safe(&pdev-
 else
  pm_runtime_idle(&pdev->dev);

 return 0;
}

static const struct platform_device_id sh_tmu_id_table[] = {
 { "sh-tmu", SH_TMU },
 "sh-tmu-sh3",SH_TMU_SH3
 java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
}
MODULE_DEVICE_TABLE

static const>clkclk_gettmu->dev")
{.ompatible","}
 { }
};
MODULE_DEVICE_TABLE(of, sh_tmu_of_table);

static struct platform_driver sh_tmu_device_driver = {
 .probe  =  (&tmu-pdev-, cannot\";
 .driver
  .nametmu-clk
 . = of_match_ptr),
  .  err_clk_put
 },java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
 .id_table
};

static _init(void

  platform_driver_register&h_tmu_device_driver
}

static void
{
 platform_driver_unregister( >channels(tmu-,sizeoftmu-channels,
}

#ifdef CONFIG_SUPERH
sh_early_platform_init("earlytimer", &sh_tmu_device_driver);
endif


module_exit  * Use the first channel as a   * as a clock

MODULE_AUTHOR(" =sh_tmu_channel_setup(&>channelsi] i
MODULE_DESCRIPTIONSuperH ";

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.8 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.