/* * This vector maps irq numbers to the bits in the bit field used in * communication with the PRCMU firmware. * * The reason for having this is to keep the irq numbers contiguous even though * the bits in the bit field are not. (The bits also have a tendency to move * around, to further complicate matters.)
*/ #define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name)) #define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name)
/* * mb0_transfer - state needed for mailbox 0 communication. * @lock: The transaction lock. * @dbb_events_lock: A lock used to handle concurrent access to (parts of) * the request data. * @mask_work: Work structure used for (un)masking wakeup interrupts. * @req: Request data that need to persist between requests.
*/ staticstruct {
spinlock_t lock;
spinlock_t dbb_irqs_lock; struct work_struct mask_work; struct mutex ac_wake_lock; struct completion ac_wake_work; struct {
u32 dbb_irqs;
u32 dbb_wakeups;
u32 abb_events;
} req;
} mb0_transfer;
/* * mb1_transfer - state needed for mailbox 1 communication. * @lock: The transaction lock. * @work: The transaction completion structure. * @ape_opp: The current APE OPP. * @ack: Reply ("acknowledge") data.
*/ staticstruct { struct mutex lock; struct completion work;
u8 ape_opp; struct {
u8 header;
u8 arm_opp;
u8 ape_opp;
u8 ape_voltage_status;
} ack;
} mb1_transfer;
/* * mb2_transfer - state needed for mailbox 2 communication. * @lock: The transaction lock. * @work: The transaction completion structure. * @auto_pm_lock: The autonomous power management configuration lock. * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled. * @req: Request data that need to persist between requests. * @ack: Reply ("acknowledge") data.
*/ staticstruct { struct mutex lock; struct completion work;
spinlock_t auto_pm_lock; bool auto_pm_enabled; struct {
u8 status;
} ack;
} mb2_transfer;
/* * mb3_transfer - state needed for mailbox 3 communication. * @lock: The request lock. * @sysclk_lock: A lock used to handle concurrent sysclk requests. * @sysclk_work: Work structure used for sysclk requests.
*/ staticstruct {
spinlock_t lock; struct mutex sysclk_lock; struct completion sysclk_work;
} mb3_transfer;
/* * mb4_transfer - state needed for mailbox 4 communication. * @lock: The transaction lock. * @work: The transaction completion structure.
*/ staticstruct { struct mutex lock; struct completion work;
} mb4_transfer;
/** * prcmu_set_rc_a2p - This function is used to run few power state sequences * @val: Value to be set, i.e. transition requested * Returns: 0 on success, -EINVAL on invalid argument * * This function is used to run the following power state sequences - * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
*/ int prcmu_set_rc_a2p(enum romcode_write val)
{ if (val < RDY_2_DS || val > RDY_2_XP70_RST) return -EINVAL;
writeb(val, (tcdm_base + PRCM_ROMCODE_A2P)); return 0;
}
/** * prcmu_get_rc_p2a - This function is used to get power state sequences * Returns: the power transition that has last happened * * This function can return the following transitions- * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
*/ enum romcode_read prcmu_get_rc_p2a(void)
{ return readb(tcdm_base + PRCM_ROMCODE_P2A);
}
/** * prcmu_get_xp70_current_state - Return the current XP70 power mode * Returns: Returns the current AP(ARM) power mode: init, * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset
*/ enum ap_pwrst prcmu_get_xp70_current_state(void)
{ return readb(tcdm_base + PRCM_XP70_CUR_PWR_STATE);
}
/** * prcmu_config_clkout - Configure one of the programmable clock outputs. * @clkout: The CLKOUT number (0 or 1). * @source: The clock to be used (one of the PRCMU_CLKSRC_*). * @div: The divider to be applied. * * Configures one of the programmable clock outputs (CLKOUTs). * @div should be in the range [1,63] to request a configuration, or 0 to * inform that the configuration is no longer requested.
*/ int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
{ staticint requests[2]; int r = 0; unsignedlong flags;
u32 val;
u32 bits;
u32 mask;
u32 div_mask;
/* This function should only be called while mb0_transfer.lock is held. */ staticvoid config_wakeups(void)
{ const u8 header[2] = {
MB0H_CONFIG_WAKEUPS_EXE,
MB0H_CONFIG_WAKEUPS_SLEEP
}; static u32 last_dbb_events; static u32 last_abb_events;
u32 dbb_events;
u32 abb_events; unsignedint i;
/** * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP * @opp: The new ARM operating point to which transition is to be made * Returns: 0 on success, non-zero on failure * * This function sets the operating point of the ARM.
*/ int db8500_prcmu_set_arm_opp(u8 opp)
{ int r;
if (opp < ARM_NO_CHANGE || opp > ARM_EXTCLK) return -EINVAL;
r = 0;
mutex_lock(&mb1_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
(mb1_transfer.ack.arm_opp != opp))
r = -EIO;
mutex_unlock(&mb1_transfer.lock);
return r;
}
/** * db8500_prcmu_get_arm_opp - get the current ARM OPP * * Returns: the current ARM OPP
*/ int db8500_prcmu_get_arm_opp(void)
{ return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
}
/** * db8500_prcmu_get_ddr_opp - get the current DDR OPP * * Returns: the current DDR OPP
*/ int db8500_prcmu_get_ddr_opp(void)
{ return readb(PRCM_DDR_SUBSYS_APE_MINBW);
}
/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ staticvoid request_even_slower_clocks(bool enable)
{
u32 clock_reg[] = {
PRCM_ACLK_MGT,
PRCM_DMACLK_MGT
}; unsignedlong flags; unsignedint i;
spin_lock_irqsave(&clk_mgt_lock, flags);
/* Grab the HW semaphore. */ while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
cpu_relax();
for (i = 0; i < ARRAY_SIZE(clock_reg); i++) {
u32 val;
u32 div;
val = readl(prcmu_base + clock_reg[i]);
div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); if (enable) { if ((div <= 1) || (div > 15)) {
pr_err("prcmu: Bad clock divider %d in %s\n",
div, __func__); goto unlock_and_return;
}
div <<= 1;
} else { if (div <= 2) goto unlock_and_return;
div >>= 1;
}
val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
(div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
writel(val, prcmu_base + clock_reg[i]);
}
unlock_and_return: /* Release the HW semaphore. */
writel(0, PRCM_SEM);
spin_unlock_irqrestore(&clk_mgt_lock, flags);
}
/** * db8500_prcmu_set_ape_opp - set the appropriate APE OPP * @opp: The new APE operating point to which transition is to be made * Returns: 0 on success, non-zero on failure * * This function sets the operating point of the APE.
*/ int db8500_prcmu_set_ape_opp(u8 opp)
{ int r = 0;
if (opp == mb1_transfer.ape_opp) return 0;
mutex_lock(&mb1_transfer.lock);
if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)
request_even_slower_clocks(false);
if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP)) goto skip_message;
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
(mb1_transfer.ack.ape_opp != opp))
r = -EIO;
skip_message: if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
(r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)))
request_even_slower_clocks(true); if (!r)
mb1_transfer.ape_opp = opp;
mutex_unlock(&mb1_transfer.lock);
return r;
}
/** * db8500_prcmu_get_ape_opp - get the current APE OPP * * Returns: the current APE OPP
*/ int db8500_prcmu_get_ape_opp(void)
{ return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
}
/** * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage * @enable: true to request the higher voltage, false to drop a request. * * Calls to this function to enable and disable requests must be balanced.
*/ int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
{ int r = 0;
u8 header; staticunsignedint requests;
mutex_lock(&mb1_transfer.lock);
if (enable) { if (0 != requests++) goto unlock_and_return;
header = MB1H_REQUEST_APE_OPP_100_VOLT;
} else { if (requests == 0) {
r = -EIO; goto unlock_and_return;
} elseif (1 != requests--) { goto unlock_and_return;
}
header = MB1H_RELEASE_APE_OPP_100_VOLT;
}
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
/** * prcmu_release_usb_wakeup_state - release the state required by a USB wakeup * * This function releases the power state requirements of a USB wakeup.
*/ int prcmu_release_usb_wakeup_state(void)
{ int r = 0;
mutex_lock(&mb1_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
r = -EIO;
mutex_unlock(&mb1_transfer.lock);
return r;
}
/** * db8500_prcmu_set_epod - set the state of a EPOD (power domain) * @epod_id: The EPOD to set * @epod_state: The new EPOD state * * This function sets the state of a EPOD (power domain). It may not be called * from interrupt context.
*/ int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
{ int r = 0; bool ram_retention = false; int i;
/* set flag if retention is possible */ switch (epod_id) { case EPOD_ID_SVAMMDSP: case EPOD_ID_SIAMMDSP: case EPOD_ID_ESRAM12: case EPOD_ID_ESRAM34:
ram_retention = true; break;
}
/* wait for mailbox */ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
cpu_relax();
/* fill in mailbox */ for (i = 0; i < NUM_EPOD_ID; i++)
writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i));
writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id));
/* * The current firmware version does not handle errors correctly, * and we cannot recover if there is an error. * This is expected to change when the firmware is updated.
*/ if (!wait_for_completion_timeout(&mb2_transfer.work,
msecs_to_jiffies(20000))) {
pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
__func__);
r = -EIO; goto unlock_and_return;
}
if (mb2_transfer.ack.status != HWACC_PWR_ST_OK)
r = -EIO;
/* * The autonomous power management configuration is done through * fields in mailbox 2, but these fields are only used as shared * variables - i.e. there is no need to send a message.
*/
writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
/* * The firmware only sends an ACK if we want to enable the * SysClk, and it succeeds.
*/ if (enable && !wait_for_completion_timeout(&mb3_transfer.sysclk_work,
msecs_to_jiffies(20000))) {
pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
__func__);
r = -EIO;
}
mutex_unlock(&mb3_transfer.sysclk_lock);
return r;
}
staticint request_timclk(bool enable)
{
u32 val;
/* * On the U8420_CLKSEL firmware, the ULP (Ultra Low Power) * PLL is disabled so we cannot use doze mode, this will * stop the clock on this firmware.
*/ if (prcmu_is_ulppll_disabled())
val = 0; else
val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
if (!enable)
val |= PRCM_TCR_STOP_TIMERS |
PRCM_TCR_DOZE_MODE |
PRCM_TCR_TENSEL_MASK;
val = readl(PRCM_PLLDSI_ENABLE); if (enable)
val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; else
val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
writel(val, PRCM_PLLDSI_ENABLE);
if (enable) { unsignedint i; bool locked = plldsi_locked();
for (i = 10; !locked && (i > 0); --i) {
udelay(100);
locked = plldsi_locked();
} if (locked) {
writel(PRCM_APE_RESETN_DSIPLL_RESETN,
PRCM_APE_RESETN_SET);
} else {
writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
PRCM_MMIP_LS_CLAMP_SET);
val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
writel(val, PRCM_PLLDSI_ENABLE);
r = -EAGAIN;
}
} else {
writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR);
} return r;
}
staticint request_dsiclk(u8 n, bool enable)
{
u32 val;
val = readl(PRCM_DSI_PLLOUT_SEL);
val &= ~dsiclk[n].divsel_mask;
val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
dsiclk[n].divsel_shift);
writel(val, PRCM_DSI_PLLOUT_SEL); return 0;
}
staticint request_dsiescclk(u8 n, bool enable)
{
u32 val;
/** * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. * @clock: The clock for which the request is made. * @enable: Whether the clock should be enabled (true) or disabled (false). * * This function should only be used by the clock implementation. * Do not use it from any other place!
*/ int db8500_prcmu_request_clock(u8 clock, bool enable)
{ if (clock == PRCMU_SGACLK) return request_sga_clock(clock, enable); elseif (clock < PRCMU_NUM_REG_CLOCKS) return request_clock(clock, enable); elseif (clock == PRCMU_TIMCLK) return request_timclk(enable); elseif ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) return request_dsiclk((clock - PRCMU_DSI0CLK), enable); elseif ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable); elseif (clock == PRCMU_PLLDSI) return request_plldsi(enable); elseif (clock == PRCMU_SYSCLK) return request_sysclk(enable); elseif ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1)) return request_pll(clock, enable); else return -EINVAL;
}
staticunsignedlong pll_rate(void __iomem *reg, unsignedlong src_rate, int branch)
{
u64 rate;
u32 val;
u32 d;
u32 div = 1;
/* The DB8520 has slightly higher ARMSS max frequency */ staticconstunsignedlong db8520_armss_freqs[] = {
199680000,
399360000,
798720000,
1152000000
};
staticlong round_armss_rate(unsignedlong rate)
{ unsignedlong freq = 0; constunsignedlong *freqs; int nfreqs; int i;
val = readl(PRCM_DSI_PLLOUT_SEL);
val &= ~dsiclk[n].divsel_mask;
val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
writel(val, PRCM_DSI_PLLOUT_SEL);
}
staticvoid set_dsiescclk_rate(u8 n, unsignedlong rate)
{
u32 val;
u32 div;
div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
val = readl(PRCM_DSITVCLK_DIV);
val &= ~dsiescclk[n].div_mask;
val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
writel(val, PRCM_DSITVCLK_DIV);
}
/* * timeout is 28 bit, in ms.
*/ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
{ return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
(id & A9WDOG_ID_MASK) | /* * Put the lowest 28 bits of timeout at * offset 4. Four first bits are used for id.
*/
(u8)((timeout << 4) & 0xf0),
(u8)((timeout >> 4) & 0xff),
(u8)((timeout >> 12) & 0xff),
(u8)((timeout >> 20) & 0xff));
}
EXPORT_SYMBOL(db8500_prcmu_load_a9wdog);
/** * prcmu_abb_read() - Read register value(s) from the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The read out value(s). * @size: The number of registers to read. * * Reads register value(s) from the ABB. * @size has to be 1 for the current firmware version.
*/ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{ int r;
if (size != 1) return -EINVAL;
mutex_lock(&mb5_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
if (!wait_for_completion_timeout(&mb5_transfer.work,
msecs_to_jiffies(20000))) {
pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
__func__);
r = -EIO;
} else {
r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
}
if (!r)
*value = mb5_transfer.ack.value;
mutex_unlock(&mb5_transfer.lock);
return r;
}
/** * prcmu_abb_write_masked() - Write masked register value(s) to the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The value(s) to write. * @mask: The mask(s) to use. * @size: The number of registers to write. * * Writes masked register value(s) to the ABB. * For each @value, only the bits set to 1 in the corresponding @mask * will be written. The other bits are not changed. * @size has to be 1 for the current firmware version.
*/ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
{ int r;
if (size != 1) return -EINVAL;
mutex_lock(&mb5_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
cpu_relax();
if (!wait_for_completion_timeout(&mb5_transfer.work,
msecs_to_jiffies(20000))) {
pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
__func__);
r = -EIO;
} else {
r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
}
mutex_unlock(&mb5_transfer.lock);
return r;
}
/** * prcmu_abb_write() - Write register value(s) to the ABB. * @slave: The I2C slave address. * @reg: The (start) register address. * @value: The value(s) to write. * @size: The number of registers to write. * * Writes register value(s) to the ABB. * @size has to be 1 for the current firmware version.
*/ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
u8 mask = ~0;
/** * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem
*/ int prcmu_ac_wake_req(void)
{
u32 val; int ret = 0;
mutex_lock(&mb0_transfer.ac_wake_lock);
val = readl(PRCM_HOSTACCESS_REQ); if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) goto unlock_and_return;
atomic_set(&ac_wake_req_state, 1);
/* * Force Modem Wake-up before hostaccess_req ping-pong. * It prevents Modem to enter in Sleep while acking the hostaccess * request. The 31us delay has been calculated by HWI.
*/
val |= PRCM_HOSTACCESS_REQ_WAKE_REQ;
writel(val, PRCM_HOSTACCESS_REQ);
udelay(31);
val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ;
writel(val, PRCM_HOSTACCESS_REQ);
if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
msecs_to_jiffies(5000))) {
pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
__func__);
ret = -EFAULT;
}
if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
msecs_to_jiffies(5000))) {
pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
__func__);
}
/** * db8500_prcmu_system_reset - System reset * * Saves the reset reason code and then sets the APE_SOFTRST register which * fires interrupt to fw * * @reset_code: The reason for system reset
*/ void db8500_prcmu_system_reset(u16 reset_code)
{
writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
writel(1, PRCM_APE_SOFTRST);
}
/** * db8500_prcmu_get_reset_code - Retrieve SW reset reason code * * Retrieves the reset reason code stored by prcmu_system_reset() before * last restart.
*/
u16 db8500_prcmu_get_reset_code(void)
{ return readw(tcdm_base + PRCM_SW_RST_REASON);
}
/** * db8500_prcmu_modem_reset - ask the PRCMU to reset modem
*/ void db8500_prcmu_modem_reset(void)
{
mutex_lock(&mb1_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4); switch (header) { case MB4H_MEM_ST: case MB4H_HOTDOG: case MB4H_HOTMON: case MB4H_HOT_PERIOD: case MB4H_A9WDOG_CONF: case MB4H_A9WDOG_EN: case MB4H_A9WDOG_DIS: case MB4H_A9WDOG_LOAD: case MB4H_A9WDOG_KICK: break; default:
print_unknown_header_warning(4, header);
do_complete = false; break;
}
staticchar *fw_project_name(u32 project)
{ switch (project) { case PRCMU_FW_PROJECT_U8500: return"U8500"; case PRCMU_FW_PROJECT_U8400: return"U8400"; case PRCMU_FW_PROJECT_U9500: return"U9500"; case PRCMU_FW_PROJECT_U8500_MBB: return"U8500 MBB"; case PRCMU_FW_PROJECT_U8500_C1: return"U8500 C1"; case PRCMU_FW_PROJECT_U8500_C2: return"U8500 C2"; case PRCMU_FW_PROJECT_U8500_C3: return"U8500 C3"; case PRCMU_FW_PROJECT_U8500_C4: return"U8500 C4"; case PRCMU_FW_PROJECT_U9500_MBL: return"U9500 MBL"; case PRCMU_FW_PROJECT_U8500_SSG1: return"U8500 Samsung 1"; case PRCMU_FW_PROJECT_U8500_MBL2: return"U8500 MBL2"; case PRCMU_FW_PROJECT_U8520: return"U8520 MBL"; case PRCMU_FW_PROJECT_U8420: return"U8420"; case PRCMU_FW_PROJECT_U8500_SSG2: return"U8500 Samsung 2";
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ 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.0.14Bemerkung:
(vorverarbeitet)
¤
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.